# Coder Documentation

> Coder is a self-hosted platform for running AI coding agents and cloud development environments on infrastructure you control. It works with any cloud, IDE, OS, Git provider, and IDP.

Every page below is also available as raw Markdown by appending `.md` to its URL or by sending `Accept: text/markdown`. Full corpus: https://coder.com/docs/llms-full.txt

## Pages

- [About](https://coder.com/docs.md): Coder is a self-hosted platform for running AI coding agents and cloud development environments on the infrastructure you control.
  - [Screenshots](https://coder.com/docs/about/screenshots.md): See screenshots of the Coder platform, including browser-based workspace access and the admin dashboard.
  - [Support](https://coder.com/docs/support.md): Get help with your Coder deployment through GitHub issues, our Discord community, and premium support.
    - [Generate and upload a support bundle to Coder Support](https://coder.com/docs/support/support-bundle.md): Generate a support bundle and share workspace and deployment diagnostics with Coder support to troubleshoot issues.
- [Quickstart](https://coder.com/docs/get-started.md): Install Coder, build your first template, and launch your first workspace in this quickstart guide.
  - [Customize your template](https://coder.com/docs/get-started/customize-your-template.md): Add a language, install command-line tools, and authenticate to GitHub
    - [Add a programming language to your template](https://coder.com/docs/get-started/customize-your-template/add-a-language.md): Expose a new programming language through a template parameter and install it at workspace startup.
    - [Install your own command-line tools](https://coder.com/docs/get-started/customize-your-template/install-command-line-tools.md): Install your own command-line tools in a workspace and make them persist across rebuilds.
    - [Clone private repositories](https://coder.com/docs/get-started/customize-your-template/authenticate-to-github.md): Clone private GitHub repositories in your workspace using a Coder external-auth data source.
- [Install Coder in your infrastructure](https://coder.com/docs/install.md): Plan, prepare, install, validate, and operate a Coder deployment in your own infrastructure.
  - [Install the Coder CLI](https://coder.com/docs/install/cli.md): Install the standalone Coder CLI binary on Linux, macOS, or Windows to run the control plane and client.
  - [1. Plan your deployment](https://coder.com/docs/install/plan.md): Learn the architecture, size the deployment, and record the decisions that shape it.
    - [Architecture](https://coder.com/docs/install/plan/architecture.md): Learn about Coder's architecture and the components that make up a deployment.
    - [Coder Validated Architecture](https://coder.com/docs/install/plan/sizing.md): Reference designs and best practices for sizing a Coder deployment, from 1,000 to 10,000 users.
      - [Reference architecture: up to 1,000 users](https://coder.com/docs/install/plan/sizing/1k-users.md): Hardware specifications and architecture guidance for Coder deployments that support up to 1,000 users
      - [Reference architecture: up to 2,000 users](https://coder.com/docs/install/plan/sizing/2k-users.md): Hardware specifications and architecture guidance for Coder deployments that support up to 2,000 users
      - [Reference architecture: up to 3,000 users](https://coder.com/docs/install/plan/sizing/3k-users.md): Enterprise-scale architecture recommendations for Coder deployments that support up to 3,000 users
      - [Reference architecture: up to 10,000 users](https://coder.com/docs/install/plan/sizing/10k-users.md): Enterprise-scale architecture recommendations for Coder deployments that support up to 10,000 users
  - [2. Prepare prerequisites](https://coder.com/docs/install/prepare.md): Gather the DNS records, certificates, database, license, and identity provider application a deployment needs.
    - [Licensing](https://coder.com/docs/install/prepare/licensing.md): Add and manage Coder licenses to unlock Premium and AI Governance features.
    - [Air-gapped Deployments](https://coder.com/docs/install/prepare/airgap.md): Run Coder in air-gapped, disconnected, or offline environments where all features remain supported.
    - [Mirror the Coder Registry with JFrog Artifactory](https://coder.com/docs/install/prepare/registry-mirror.md): Use JFrog Artifactory to mirror the Coder Registry for air-gapped deployments
  - [3. Install the control plane](https://coder.com/docs/install/server.md): Choose a platform and install the Coder control plane on it.
    - [Install Coder via Docker](https://coder.com/docs/install/server/docker.md): Install and run Coder using the official Docker images for a quick single-machine deployment.
    - [Install Coder on Kubernetes](https://coder.com/docs/install/server/kubernetes.md): Install Coder on a Kubernetes cluster using the official Helm chart for production deployments.
      - [Deploy Coder on Azure with an Application Gateway](https://coder.com/docs/install/server/kubernetes/kubernetes-azure-app-gateway.md): Deploy Coder on Azure Kubernetes Service behind an Azure Application Gateway ingress controller.
    - [Deploy Coder on Rancher](https://coder.com/docs/install/server/rancher.md): Deploy Coder on Rancher as a Kubernetes workload using the Rancher UI and Helm.
    - [OpenShift](https://coder.com/docs/install/server/openshift.md): Install Coder on a Red Hat OpenShift cluster using Helm, with the required security context settings.
    - [Install Coder on RHEL-family Linux](https://coder.com/docs/install/server/rpm.md): Install the Coder control plane from an RPM package on Red Hat Enterprise Linux and other RHEL-family distributions.
    - [Cloud platforms](https://coder.com/docs/install/server/cloud.md): Install guides and example templates for deploying Coder on AWS, Google Cloud, and Azure.
      - [Amazon Web Services](https://coder.com/docs/install/server/cloud/aws-marketplace.md): Deploy a Coder proof-of-concept on AWS using the listing available in the AWS Marketplace.
      - [Google Cloud Platform](https://coder.com/docs/install/server/cloud/compute-engine.md): Deploy the Coder control plane on a Google Cloud Compute Engine virtual machine.
      - [Microsoft Azure](https://coder.com/docs/install/server/cloud/azure-vm.md): Set up the Coder control plane on a Microsoft Azure virtual machine, step by step.
    - [Community install methods](https://coder.com/docs/install/server/community.md): Community-contributed methods for installing Coder on platforms Coder doesn't package itself.
  - [4. Validate your deployment](https://coder.com/docs/install/validate.md): Harden the deployment, then prove it works and holds up under load.
    - [Scale Testing](https://coder.com/docs/install/validate/scale-testing.md): Plan and run scale tests to make sure your Coder deployment can handle your organization's load.
      - [Scale tests and utilities](https://coder.com/docs/install/validate/scale-testing/utility.md): Use Coder's built-in scale-testing utility to benchmark and load-test your deployment.
      - [Scale Coder](https://coder.com/docs/tutorials/best-practices/scale-coder.md): Best practices for preparing and tuning a Coder deployment so it scales to many users.
  - [5. Operate and maintain](https://coder.com/docs/install/operate.md): Run the deployment day to day, add external provisioners, upgrade it, and remove it when needed.
    - [External provisioners](https://coder.com/docs/install/operate/provisioners.md): Run external provisioner daemons to isolate builds and scale workspace provisioning.
      - [Manage provisioner jobs](https://coder.com/docs/install/operate/provisioners/manage-provisioner-jobs.md): Monitor and manage provisioner jobs for workspace builds, including canceling stuck jobs.
    - [Upgrade](https://coder.com/docs/install/operate/upgrade.md): Learn how to upgrade your Coder deployment to a newer version, with steps for each install method.
      - [Upgrade best practices](https://coder.com/docs/install/operate/upgrade/best-practices.md): Follow best practices and troubleshooting tips to plan and carry out Coder upgrades.
      - [Upgrade from ESR 2.24 to 2.29](https://coder.com/docs/install/operate/upgrade/esr-2.24-2.29-upgrade.md): A step-by-step guide to upgrade a Coder deployment from Extended Support Release 2.24 to 2.29.
      - [Upgrade from ESR 2.29 to 2.34](https://coder.com/docs/install/operate/upgrade/esr-2.29-2.34-upgrade.md): A step-by-step guide to upgrade a Coder deployment from Extended Support Release 2.29 to 2.34.
    - [Uninstall](https://coder.com/docs/install/operate/uninstall.md): Learn how to uninstall your Coder deployment and remove its associated resources.
- [User Guides](https://coder.com/docs/user-guides.md): Guides for Coder end users on accessing, managing, and personalizing their workspaces.
  - [Access your workspace](https://coder.com/docs/user-guides/workspace-access.md): Connect to your Coder workspace using SSH, your IDE, a web terminal, remote desktop, and more.
    - [Visual Studio Code](https://coder.com/docs/user-guides/workspace-access/vscode.md): Develop in your Coder workspace remotely with VS Code, using the desktop app or the browser.
    - [Web Terminal](https://coder.com/docs/user-guides/workspace-access/web-terminal.md): Use the browser-based web terminal to run commands in your workspace without any local setup.
    - [JetBrains IDEs](https://coder.com/docs/user-guides/workspace-access/jetbrains.md): Connect JetBrains IDEs to Coder workspaces using JetBrains Toolbox or Gateway.
      - [JetBrains Gateway](https://coder.com/docs/user-guides/workspace-access/jetbrains/gateway.md): Use JetBrains Gateway to open and work in your Coder workspace from a full JetBrains IDE.
      - [JetBrains Toolbox (Beta)](https://coder.com/docs/user-guides/workspace-access/jetbrains/toolbox.md): Connect to and manage your Coder workspaces from the JetBrains Toolbox app.
    - [Remote desktops](https://coder.com/docs/user-guides/workspace-access/remote-desktops.md): Connect to a GUI-based desktop in your Coder workspace using RDP, including Windows workspaces.
    - [Emacs TRAMP](https://coder.com/docs/user-guides/workspace-access/emacs-tramp.md): Use Emacs TRAMP to edit files and run commands in your Coder workspace over SSH.
    - [Workspace ports](https://coder.com/docs/user-guides/workspace-access/port-forwarding.md): Securely access ports and processes running inside your Coder workspace from your local machine.
    - [File Browser](https://coder.com/docs/user-guides/workspace-access/filebrowser.md): Upload, download, and manage files in your Coder workspace from the browser with File Browser.
    - [Web IDEs](https://coder.com/docs/user-guides/workspace-access/web-ides.md): Access your Coder workspace through web-based IDEs that run in the browser, with no local install.
    - [code-server](https://coder.com/docs/user-guides/workspace-access/code-server.md): Access your Coder workspace in the browser with code-server, the VS Code experience over the web.
    - [Zed](https://coder.com/docs/user-guides/workspace-access/zed.md): Access your Coder workspace with the Zed collaborative code editor over SSH.
    - [Cursor](https://coder.com/docs/user-guides/workspace-access/cursor.md): Access your Coder workspace with Cursor, the AI-powered code editor, over SSH.
    - [Devin Desktop](https://coder.com/docs/user-guides/workspace-access/devin-desktop.md): Access your Coder workspace with Devin Desktop (formerly Windsurf), the AI-powered code editor, over SSH.
    - [Antigravity](https://coder.com/docs/user-guides/workspace-access/antigravity.md): Access your Coder workspace with the Antigravity agentic code editor over SSH.
  - [Coder Desktop](https://coder.com/docs/user-guides/desktop.md): Transform remote workspaces into seamless local development environments with no port forwarding required
    - [Coder Desktop Connect and Sync](https://coder.com/docs/user-guides/desktop/desktop-connect-sync.md): Use Coder Desktop to connect to workspaces and sync their code and files to your local machine.
  - [Manage workspaces](https://coder.com/docs/user-guides/workspace-management.md): Create, start, stop, update, and delete your Coder workspaces from the dashboard or CLI.
  - [Shared workspaces](https://coder.com/docs/user-guides/shared-workspaces.md): Let multiple users securely connect to a single Coder workspace to program and debug together.
  - [Manage workspace schedules](https://coder.com/docs/user-guides/workspace-scheduling.md): Control cloud costs by scheduling when your Coder workspaces automatically start and stop.
  - [Workspace lifecycle](https://coder.com/docs/user-guides/workspace-lifecycle.md): A guide to the workspace lifecycle, from creation and status through stopping and deletion.
  - [Dev Containers](https://coder.com/docs/user-guides/devcontainers.md): Run containerized development environments in your Coder workspace using the dev containers specification.
    - [Work with Dev Containers](https://coder.com/docs/user-guides/devcontainers/working-with-dev-containers.md): Access and work inside dev containers in your Coder workspace over SSH, your IDE, or the web terminal.
    - [Customizing dev containers](https://coder.com/docs/user-guides/devcontainers/customizing-dev-containers.md): Configure custom agent names, apps, and display options in devcontainer.json.
    - [Troubleshooting dev containers](https://coder.com/docs/user-guides/devcontainers/troubleshooting-dev-containers.md): Diagnose and resolve common issues with dev containers in your Coder workspace.
  - [Dotfiles](https://coder.com/docs/user-guides/workspace-dotfiles.md): Personalize your Coder workspaces by applying your dotfiles repository with the coder dotfiles command.
  - [User secrets](https://coder.com/docs/user-guides/user-secrets.md): Store secret values in Coder and automatically inject them into workspaces
- [Administration](https://coder.com/docs/admin.md): Guides for the template and deployment administrators who configure, secure, and operate Coder.
  - [Configure control plane access](https://coder.com/docs/admin/setup.md): Configure your Coder control plane with server settings and environment variables.
    - [Appearance (Premium)](https://coder.com/docs/admin/setup/appearance.md): Customize your Coder deployment's appearance, including the logo, service banner, and application name.
    - [Configuration Reference](https://coder.com/docs/admin/setup/configuration-reference.md): Searchable list of every Coder server setting with its environment variable, CLI flag, and YAML key
    - [Telemetry](https://coder.com/docs/admin/setup/telemetry.md): Learn what usage telemetry Coder collects, why it is collected, and how to opt out.
    - [Configure chat lifecycle hooks](https://coder.com/docs/admin/setup/chat-lifecycle-hooks.md): Configure an external policy service for chat agent lifecycle events
    - [Data Retention](https://coder.com/docs/admin/setup/data-retention.md): Configure retention policies that automatically purge old records from Coder database tables.
  - [Users](https://coder.com/docs/admin/users.md): Learn how to create, manage, and audit users and their access in your Coder deployment.
    - [OpenID Connect](https://coder.com/docs/admin/users/oidc-auth.md): Configure OpenID Connect authentication with identity providers like Okta or Active Directory
      - [Google authentication (OIDC)](https://coder.com/docs/admin/users/oidc-auth/google.md): Configure Coder to authenticate users with Google using OpenID Connect (OIDC).
      - [Microsoft Entra ID authentication (OIDC)](https://coder.com/docs/admin/users/oidc-auth/microsoft.md): Configure Coder to authenticate users with Microsoft Entra ID using OpenID Connect (OIDC).
      - [Configure OIDC refresh tokens](https://coder.com/docs/admin/users/oidc-auth/refresh-tokens.md): Configure OIDC refresh tokens so Coder can keep user sessions active beyond token expiration.
    - [GitHub](https://coder.com/docs/admin/users/github-auth.md): Set up authentication through GitHub OAuth to enable secure user login and sign-up
    - [Password Authentication](https://coder.com/docs/admin/users/password-auth.md): Manage username/password authentication settings and user password reset workflows
    - [Headless Authentication](https://coder.com/docs/admin/users/headless-auth.md): Create and manage headless service accounts for automated systems and API integrations
    - [Groups and roles (Premium)](https://coder.com/docs/admin/users/groups-roles.md): Manage access control with user groups and role-based permissions for Coder resources
    - [IdP Sync](https://coder.com/docs/admin/users/idp-sync.md): Synchronize user groups, roles, and organizations from your identity provider to Coder
    - [Organizations (Premium)](https://coder.com/docs/admin/users/organizations.md): Segment and isolate resources by creating separate organizations for different teams or projects
    - [Quotas](https://coder.com/docs/admin/users/quotas.md): Control resource usage by implementing workspace budgets and credit-based cost management
    - [API & session tokens](https://coder.com/docs/admin/users/sessions-tokens.md): Manage authentication tokens for API access and configure session duration policies
  - [Template](https://coder.com/docs/admin/templates.md): Learn how to author, publish, and maintain the Coder templates that define your workspaces.
    - [Creating Templates](https://coder.com/docs/admin/templates/creating-templates.md): Create a Coder template with Terraform to define the infrastructure for your workspaces.
    - [Work with templates](https://coder.com/docs/admin/templates/managing-templates.md): Learn how to edit, version, and manage Coder templates, along with recommended best practices.
      - [Image Management](https://coder.com/docs/admin/templates/managing-templates/image-management.md): Learn how to build and manage the container images that back your Coder templates.
      - [Template change management](https://coder.com/docs/admin/templates/managing-templates/change-management.md): Manage Coder template changes with source control, versioning, and CI/CD publishing.
      - [Envbuilder](https://coder.com/docs/admin/templates/managing-templates/envbuilder.md): Use Envbuilder to shift workspace environment definitions from templates into your Git repositories.
      - [Template Dependencies](https://coder.com/docs/admin/templates/managing-templates/dependencies.md): Manage provider and module dependencies in your Coder templates to keep builds reproducible.
      - [Workspace Scheduling](https://coder.com/docs/admin/templates/managing-templates/schedule.md): Configure template settings that control how workspaces autostart, autostop, and stay available.
      - [External Workspaces](https://coder.com/docs/admin/templates/managing-templates/external-workspaces.md): Connect externally managed servers and machines to Coder as external workspaces.
    - [Extend templates](https://coder.com/docs/admin/templates/extending-templates.md): Extend your Coder templates with parameters, metadata, web IDEs, Docker, and more.
      - [Agent metadata](https://coder.com/docs/admin/templates/extending-templates/agent-metadata.md): Display real-time metrics from the workspace agent, such as CPU, memory, and disk usage.
      - [Parameters](https://coder.com/docs/admin/templates/extending-templates/parameters.md): Use build parameters to prompt users and customize each workspace when it is created.
      - [Dynamic Parameters](https://coder.com/docs/admin/templates/extending-templates/dynamic-parameters.md): Build conditional, identity-aware template forms with Coder's dynamic parameters.
      - [Prebuilt workspaces](https://coder.com/docs/admin/templates/extending-templates/prebuilt-workspaces.md): Pre-provision a ready-to-deploy workspace with a defined set of parameters
      - [Icons](https://coder.com/docs/admin/templates/extending-templates/icons.md): Customize your Coder templates and resources with built-in or custom icons.
      - [Resource Metadata](https://coder.com/docs/admin/templates/extending-templates/resource-metadata.md): Expose key workspace resource information to your users in the Coder dashboard with metadata.
      - [Resource monitoring](https://coder.com/docs/admin/templates/extending-templates/resource-monitoring.md): Monitor workspace resource usage and alert on thresholds from the Coder dashboard.
      - [UI resource ordering](https://coder.com/docs/admin/templates/extending-templates/resource-ordering.md): Control the order that resources and parameters appear in the workspace creation UI.
      - [Resource persistence](https://coder.com/docs/admin/templates/extending-templates/resource-persistence.md): Control which workspace resources persist across restarts and which are recreated on each build.
      - [Environment variables](https://coder.com/docs/admin/templates/extending-templates/environment-variables.md): Inject environment variables into Coder workspaces using the coder_env Terraform resource.
      - [Terraform template-wide variables](https://coder.com/docs/admin/templates/extending-templates/variables.md): Use Terraform template-wide variables to parameterize and manage your Coder templates.
      - [Reuse template code](https://coder.com/docs/admin/templates/extending-templates/modules.md): Reuse Terraform code across your Coder templates with shared, versioned modules.
      - [Web IDEs in templates](https://coder.com/docs/admin/templates/extending-templates/web-ides.md): Add and configure web IDEs in your Coder templates as coder_app resources.
      - [Pre-install JetBrains IDEs in your template](https://coder.com/docs/admin/templates/extending-templates/jetbrains-preinstall.md): Pre-install JetBrains IDE backends in your template for faster first-time connections.
      - [JetBrains IDEs in an air-gapped environment](https://coder.com/docs/admin/templates/extending-templates/jetbrains-airgapped.md): Configure JetBrains IDEs to work in air-gapped Coder deployments without internet access.
      - [Docker in Workspaces](https://coder.com/docs/admin/templates/extending-templates/docker-in-workspaces.md): Run Docker inside container-based Coder workspaces using several supported approaches.
      - [Workspace Tags](https://coder.com/docs/admin/templates/extending-templates/workspace-tags.md): Route workspace builds to specific provisioners using workspace tags and parameters.
      - [Provider Authentication](https://coder.com/docs/admin/templates/extending-templates/provider-authentication.md): Authenticate the Coder control plane to cloud provider APIs so it can provision workspaces.
      - [Dev Containers](https://coder.com/docs/admin/templates/extending-templates/devcontainers.md): Extend your Coder templates with containerized dev container development environments.
      - [Improve agent resiliency](https://coder.com/docs/admin/templates/extending-templates/process-priority.md): Improve workspace agent resiliency by tuning child process CPU and out-of-memory priority.
      - [Workspace process logging](https://coder.com/docs/admin/templates/extending-templates/process-logging.md): Log all system-level process activity inside workspaces for security and auditing.
      - [Workspace startup coordination](https://coder.com/docs/admin/templates/startup-coordination.md): Coordinate workspace startup scripts with dependency management so they run in the right order.
        - [Workspace startup coordination usage](https://coder.com/docs/admin/templates/startup-coordination/usage.md): Declare units and dependencies with coder exp sync to coordinate your workspace startup scripts.
        - [Workspace startup coordination troubleshooting](https://coder.com/docs/admin/templates/startup-coordination/troubleshooting.md): Diagnose and resolve common problems with workspace startup coordination and coder exp sync.
        - [Workspace startup coordination examples](https://coder.com/docs/admin/templates/startup-coordination/example.md): A complete, production-ready example of coordinating workspace startup scripts with sync units.
    - [Open in Coder](https://coder.com/docs/admin/templates/open-in-coder.md): Add an Open in Coder button to your repositories and wikis so users can create workspaces fast.
    - [Permissions](https://coder.com/docs/admin/templates/template-permissions.md): Control which users and groups can use, edit, and administer each Coder template.
    - [Troubleshoot templates](https://coder.com/docs/admin/templates/troubleshooting.md): Troubleshoot common Coder template problems, from failed builds to misconfigured workspaces.
  - [External Authentication](https://coder.com/docs/admin/external-auth.md): Configure external authentication so workspaces can access Git providers and other OAuth services.
  - [Integrations](https://coder.com/docs/admin/integrations.md): Extend Coder with integrations for observability, secrets, source control, and other platforms.
    - [Prometheus](https://coder.com/docs/admin/integrations/prometheus.md): Collect and export Coder deployment metrics to a Prometheus server for monitoring.
    - [Kubernetes event logs](https://coder.com/docs/admin/integrations/kubernetes-logs.md): Stream Kubernetes event logs into workspace startup logs to debug pod scheduling issues.
    - [Additional clusters](https://coder.com/docs/admin/integrations/multiple-kube-clusters.md): Deploy Coder workspaces across additional Kubernetes clusters beyond the control plane cluster.
    - [JFrog Artifactory integration](https://coder.com/docs/admin/integrations/jfrog-artifactory.md): Integrate Coder with JFrog Artifactory to secure workspaces and manage packages and tokens.
    - [Island browser integration](https://coder.com/docs/admin/integrations/island.md): Integrate Coder with the Island Enterprise Browser for secure, policy-controlled workspace access.
    - [DX PlatformX](https://coder.com/docs/admin/integrations/platformx.md): Forward Coder notifications to DX PlatformX to measure and improve developer experience.
    - [DX](https://coder.com/docs/admin/integrations/dx-data-cloud.md): Tag and sync Coder users with DX Data Cloud to measure developer productivity.
    - [Integrate HashiCorp Vault with Coder](https://coder.com/docs/admin/integrations/vault.md): Integrate Coder with HashiCorp Vault to inject secrets securely into your workspaces.
    - [OAuth2 provider](https://coder.com/docs/admin/integrations/oauth2-provider.md): Use Coder as an OAuth2 authorization server so third-party apps can authenticate users.
      - [OAuth2 provider integration patterns](https://coder.com/docs/admin/integrations/oauth2-provider/integration-patterns.md): Client authentication methods, the standard flow, the required PKCE flow, and discovery endpoints.
      - [OAuth2 provider scopes](https://coder.com/docs/admin/integrations/oauth2-provider/scopes.md): How access tokens are bounded by scope, and how to set an application's scope allowlist.
      - [OAuth2 provider token management](https://coder.com/docs/admin/integrations/oauth2-provider/token-management.md): Refresh an access token, revoke a token, and delete an OAuth2 application.
      - [OAuth2 provider callback URL schemes](https://coder.com/docs/admin/integrations/oauth2-provider/callback-url-schemes.md): Which redirect URI schemes and hosts Coder accepts.
      - [OAuth2 provider troubleshooting](https://coder.com/docs/admin/integrations/oauth2-provider/troubleshooting.md): Diagnose and fix OAuth2 provider errors by their exact error code or message.
      - [OAuth2 provider security and limitations](https://coder.com/docs/admin/integrations/oauth2-provider/security.md): Security considerations and current limitations of the OAuth2 provider.
    - [Dev Containers](https://coder.com/docs/admin/integrations/devcontainers.md): Configure dev container support in your templates using either Docker or Envbuilder.
      - [Configure a template for Dev Containers](https://coder.com/docs/admin/integrations/devcontainers/integration.md): Configure a Coder template for native dev containers backed by Docker.
      - [Envbuilder](https://coder.com/docs/admin/integrations/devcontainers/envbuilder.md): Use Envbuilder to build dev containers from a repository without requiring Docker.
        - [Add an Envbuilder template](https://coder.com/docs/admin/integrations/devcontainers/envbuilder/add-envbuilder.md): Add an Envbuilder-compatible template so users can build dev containers from a repository.
        - [Envbuilder security and caching](https://coder.com/docs/admin/integrations/devcontainers/envbuilder/envbuilder-security-caching.md): Configure Envbuilder registry authentication and layer caching for faster, secure builds.
        - [Envbuilder releases and known issues](https://coder.com/docs/admin/integrations/devcontainers/envbuilder/envbuilder-releases-known-issues.md): Learn about Envbuilder's release channels and current known issues before you deploy it.
  - [Networking](https://coder.com/docs/admin/networking.md): Understand Coder's networking model, including how workspaces, servers, and clients connect.
    - [Port Forwarding](https://coder.com/docs/admin/networking/port-forwarding.md): Learn how port forwarding works in Coder and how to expose workspace ports to users.
    - [STUN and NAT](https://coder.com/docs/admin/networking/stun.md): Learn how Coder uses STUN and NAT traversal to establish direct peer-to-peer workspace connections.
    - [Workspace proxies (Premium)](https://coder.com/docs/admin/networking/workspace-proxies.md): Run geo-distributed workspace proxies to give distributed teams low-latency workspace access.
    - [High Availability](https://coder.com/docs/admin/networking/high-availability.md): Configure Coder in high availability (HA) mode for horizontal scalability and failover.
    - [Wildcard access URLs](https://coder.com/docs/admin/networking/wildcard-access-url.md): Configure a wildcard access URL to enable port forwarding, web IDEs, and app previews.
    - [Troubleshooting](https://coder.com/docs/admin/networking/troubleshooting.md): Diagnose and resolve Coder networking issues using coder ping and other built-in tools.
  - [Monitor Coder](https://coder.com/docs/admin/monitoring.md): Monitor your Coder deployment with logs, metrics, health checks, and alerting best practices.
    - [Logs](https://coder.com/docs/admin/monitoring/logs.md): Learn how Coder services write logs to standard output and how to collect them.
    - [Deployment metrics](https://coder.com/docs/admin/monitoring/metrics.md): Learn about the deployment metrics Coder exposes and how to use them to monitor health.
    - [Deployment health](https://coder.com/docs/admin/monitoring/health-check.md): Use Coder's deployment health page to monitor your control plane and its dependencies.
    - [Connection logs (Premium)](https://coder.com/docs/admin/monitoring/connection-logs.md): Monitor SSH, app, and agent connections to your workspaces with the connection log.
    - [Notifications](https://coder.com/docs/admin/monitoring/notifications.md): Configure how Coder sends notifications for deployment events over email and webhooks.
      - [Slack Notifications](https://coder.com/docs/admin/monitoring/notifications/slack.md): Set up a Slack integration to deliver Coder notifications to your channels.
      - [Microsoft Teams Notifications](https://coder.com/docs/admin/monitoring/notifications/teams.md): Set up a Microsoft Teams integration to deliver Coder notifications to your channels.
  - [Security](https://coder.com/docs/admin/security.md): Secure your Coder deployment with audit logs, secrets management, and database encryption.
    - [Audit Logs](https://coder.com/docs/admin/security/audit-logs.md): Track user and administrator actions across your Coder deployment with audit logs.
    - [Secrets](https://coder.com/docs/admin/security/secrets.md): Learn the recommended ways to get secrets into your Coder workspaces securely.
    - [Database Encryption](https://coder.com/docs/admin/security/database-encryption.md): Encrypt sensitive values in the Coder database to protect tokens and secrets at rest.
- [Run AI Coding Agents in Coder](https://coder.com/docs/ai-coder.md): Run and manage AI coding agents like Claude Code and Codex in Coder workspaces, alongside your existing development environments.
  - [Best Practices](https://coder.com/docs/ai-coder/best-practices.md): Cultural and technical best practices for introducing AI coding agents into your organization.
  - [In the IDE](https://coder.com/docs/ai-coder/ide-agents.md): Run in-IDE AI coding assistants and agents while backing their compute with Coder workspaces.
  - [Coder Agents](https://coder.com/docs/ai-coder/agents.md): Delegate development work to coding agents in your deployment with Coder Agents, a chat interface and API.
    - [Getting Started](https://coder.com/docs/ai-coder/agents/getting-started.md): Enable Coder Agents, prepare your deployment, and run your first Coder Agent
    - [Architecture](https://coder.com/docs/ai-coder/agents/architecture.md): Learn how the Coder Agents control-plane agent communicates with your workspaces.
    - [Platform Controls](https://coder.com/docs/ai-coder/agents/platform-controls.md): Learn how platform teams control Coder Agents behavior, models, spend, and policies.
      - [Template Optimization](https://coder.com/docs/ai-coder/agents/platform-controls/template-optimization.md): Best practices for creating templates that are discoverable and useful to Coder Agents
      - [Organization scope](https://coder.com/docs/ai-coder/agents/platform-controls/organizations.md): Learn which Coder Agents settings belong to an organization, what an upgrade migrates, and who can change them.
      - [Network isolation](https://coder.com/docs/ai-coder/agents/platform-controls/agent-isolation.md): Run Coder Agents in a separate sandbox with a two-Pod Kubernetes template.
      - [MCP Servers](https://coder.com/docs/ai-coder/agents/platform-controls/mcp-servers.md): Configure external MCP servers that provide additional tools for agent chat sessions
      - [Spend management (Premium)](https://coder.com/docs/ai-coder/agents/platform-controls/spend-management.md): Cap Coder Agents spend with AI Gateway budgets and track the resulting spend.
      - [Git Providers](https://coder.com/docs/ai-coder/agents/platform-controls/git-providers.md): Configure Git providers so Coder Agents can show pull request diffs in the in-chat viewer.
      - [Conversation data retention](https://coder.com/docs/ai-coder/agents/platform-controls/chat-retention.md): Configure automatic cleanup of old Coder Agents conversation data to manage database size.
      - [Chat debug data retention](https://coder.com/docs/ai-coder/agents/platform-controls/chat-debug-retention.md): Configure automatic cleanup of old Coder Agents chat debug data to manage database size.
      - [Conversation auto-archive](https://coder.com/docs/ai-coder/agents/platform-controls/chat-auto-archive.md): Automatically archive long-inactive Coder Agents conversations to keep chat lists tidy.
      - [Advisor](https://coder.com/docs/ai-coder/agents/platform-controls/advisor.md): Provide strategic, high-level guidance to root Coder Agents chats with the Advisor.
      - [Virtual desktop](https://coder.com/docs/ai-coder/agents/platform-controls/virtual-desktop.md): Give Coder Agents a graphical virtual desktop inside workspaces for GUI-based tasks.
      - [Chat debug logging](https://coder.com/docs/ai-coder/agents/platform-controls/chat-debug-logging.md): Record detailed traces of each Coder Agents chat turn to troubleshoot agent behavior.
    - [Extending Agents](https://coder.com/docs/ai-coder/agents/extending-agents.md): Extend Coder Agents with custom skills and MCP tools defined in your workspace templates.
    - [Models](https://coder.com/docs/ai-coder/agents/models.md): Configure the LLM providers and models that power Coder Agents from Admin settings.
    - [Tools](https://coder.com/docs/ai-coder/agents/tools.md): How Coder Agents uses tool calls to select templates and create workspaces
    - [Chat Sharing](https://coder.com/docs/ai-coder/agents/chat-sharing.md): Give other users and groups read-only access to a Coder Agents conversation with chat sharing.
    - [Conversation search syntax](https://coder.com/docs/ai-coder/agents/chat-search-syntax.md): Filter Coder Agents conversations by title, status, and linked pull requests with search syntax.
    - [Licensing & Usage](https://coder.com/docs/ai-coder/agents/licensing-usage.md): Compare Coder Agents licenses and learn how Coder measures and reports Agent Time usage.
    - [Migrate from the Tasks API to the Chats API](https://coder.com/docs/ai-coder/agents/tasks-to-chats-migration.md): Migrate your integrations from the removed Coder Tasks API to the Coder Agents Chats API.
  - [Agent Relay](https://coder.com/docs/ai-coder/agent-relay.md): Connect supported cloud-hosted AI agents to self-hosted Coder workspaces with Agent Relay.
    - [Agent Relay for Cursor](https://coder.com/docs/ai-coder/agent-relay/cursor.md): Run Cursor's cloud agent sessions inside self-hosted Coder workspaces with Agent Relay.
    - [Agent Relay for Claude Code](https://coder.com/docs/ai-coder/agent-relay/claude-code.md): Run Claude Code's cloud sessions inside self-hosted Coder workspaces with Agent Relay.
  - [AI Governance](https://coder.com/docs/ai-coder/ai-governance.md): Govern AI usage at scale with AI Governance: Agent Firewall, AI Gateway, and reporting.
    - [Agent Firewall](https://coder.com/docs/ai-coder/agent-firewall.md): Restrict and audit the network access of AI agents with Agent Firewall, a process-level firewall.
      - [nsjail jail type](https://coder.com/docs/ai-coder/agent-firewall/nsjail.md): Learn how Agent Firewall's default nsjail jail type isolates agents using Linux namespaces.
        - [nsjail on Docker](https://coder.com/docs/ai-coder/agent-firewall/nsjail/docker.md): Runtime and permission requirements for running Agent Firewall's nsjail jail type on Docker.
        - [nsjail on Kubernetes](https://coder.com/docs/ai-coder/agent-firewall/nsjail/k8s.md): Runtime and permission requirements for running Agent Firewall's nsjail jail type on Kubernetes.
        - [nsjail on ECS](https://coder.com/docs/ai-coder/agent-firewall/nsjail/ecs.md): Runtime and permission requirements for running Agent Firewall's nsjail jail type on AWS ECS.
      - [landjail jail type](https://coder.com/docs/ai-coder/agent-firewall/landjail.md): Learn how Agent Firewall's landjail jail type isolates agents using Landlock v4.
      - [Rules engine documentation](https://coder.com/docs/ai-coder/agent-firewall/rules-engine.md): Learn how the Agent Firewall rules engine filters agent network requests with configurable rules.
      - [Version requirements](https://coder.com/docs/ai-coder/agent-firewall/version.md): Check the Coder and Claude Code module version requirements for running Agent Firewall.
    - [AI Gateway](https://coder.com/docs/ai-coder/ai-gateway.md): Govern and observe AI coding traffic with AI Gateway.
      - [Setup](https://coder.com/docs/ai-coder/ai-gateway/setup.md): Enable and configure AI Gateway inside the Coder control plane, with no extra compute to deploy.
      - [Deploy AI Gateway as a standalone service](https://coder.com/docs/ai-coder/ai-gateway/standalone.md): Deploy and operate AI Gateway as a standalone service
      - [Authentication](https://coder.com/docs/ai-coder/ai-gateway/auth.md): Authenticate AI coding tools against AI Gateway using your Coder API token.
      - [Client Configuration](https://coder.com/docs/ai-coder/ai-gateway/clients.md): Configure your AI coding tools to route their model requests through AI Gateway.
        - [Claude Code](https://coder.com/docs/ai-coder/ai-gateway/clients/claude-code.md): Configure Claude Code to route requests through AI Gateway using environment variables.
        - [Codex CLI](https://coder.com/docs/ai-coder/ai-gateway/clients/codex.md): Configure the Codex CLI to route requests through AI Gateway with a custom model provider.
        - [Xum](https://coder.com/docs/ai-coder/ai-gateway/clients/xum.md): Configure Xum, the parallel coding agent tool, to route requests through AI Gateway.
        - [OpenCode](https://coder.com/docs/ai-coder/ai-gateway/clients/opencode.md): Configure OpenCode to route its OpenAI and Anthropic requests through AI Gateway.
        - [Factory](https://coder.com/docs/ai-coder/ai-gateway/clients/factory.md): Configure Factory's Droid agent to route its model requests through AI Gateway.
        - [Cline](https://coder.com/docs/ai-coder/ai-gateway/clients/cline.md): Configure Cline to route its OpenAI and Anthropic requests through AI Gateway.
        - [Kilo Code](https://coder.com/docs/ai-coder/ai-gateway/clients/kilo-code.md): Configure Kilo Code to route its model requests through AI Gateway from the UI.
        - [VS Code](https://coder.com/docs/ai-coder/ai-gateway/clients/vscode.md): Configure VS Code to route its AI model requests through Coder's AI Gateway.
        - [JetBrains](https://coder.com/docs/ai-coder/ai-gateway/clients/jetbrains.md): Configure JetBrains AI Assistant to route model requests through AI Gateway.
        - [Junie](https://coder.com/docs/ai-coder/ai-gateway/clients/junie.md): Configure Junie CLI to route requests through AI Gateway with a custom model profile.
        - [Zed](https://coder.com/docs/ai-coder/ai-gateway/clients/zed.md): Configure the Zed editor's language models to route requests through AI Gateway.
        - [GitHub Copilot](https://coder.com/docs/ai-coder/ai-gateway/clients/copilot.md): Route GitHub Copilot model requests through AI Gateway using the AI Gateway Proxy.
      - [MCP](https://coder.com/docs/ai-coder/ai-gateway/mcp.md): Connect MCP servers to AI Gateway to inject tools and centrally manage what users can call.
      - [AI Gateway Proxy](https://coder.com/docs/ai-coder/ai-gateway/ai-gateway-proxy.md): Use AI Gateway Proxy to route AI tools that don't support base URL overrides through AI Gateway.
        - [Setup](https://coder.com/docs/ai-coder/ai-gateway/ai-gateway-proxy/setup.md): Enable and configure AI Gateway Proxy inside the Coder control plane, with no extra compute.
      - [Provider Configuration](https://coder.com/docs/ai-coder/ai-gateway/providers.md): Learn how AI Gateway stores and reloads LLM provider configuration for your deployment.
      - [Audit AI sessions](https://coder.com/docs/ai-coder/ai-gateway/audit.md): Audit AI coding sessions and threads captured by AI Gateway for governance and review.
      - [Monitoring](https://coder.com/docs/ai-coder/ai-gateway/monitoring.md): Monitor AI Gateway activity, including prompts, token usage, and tool calls per request.
      - [AI Governance Cost Control](https://coder.com/docs/ai-coder/ai-gateway/cost-controls.md): Configure AI Gateway budgets, enforcement, notifications, and spend reporting.
      - [Reference](https://coder.com/docs/ai-coder/ai-gateway/reference.md): Technical reference for AI Gateway, including deployment topologies, version compatibility, and supported APIs.
      - [Rebranding Migration](https://coder.com/docs/ai-coder/ai-gateway/rebranding-migration.md): Update configuration and references after the AI Bridge rename to AI Gateway.
  - [MCP Server](https://coder.com/docs/ai-coder/mcp-server.md): Connect external AI coding agents to Coder using its built-in Model Context Protocol server.
- [Guides and tutorials](https://coder.com/docs/tutorials.md): Step-by-step, employee-written guides and tutorials for deploying and administering Coder.
  - [Quickstart](https://coder.com/docs/get-started.md): Install Coder, build your first template, and launch your first workspace in this quickstart guide.
  - [Write a template from scratch](https://coder.com/docs/tutorials/template-from-scratch.md): Learn how to write a Coder template from scratch with Terraform, step by step.
  - [Use Coder with an external database](https://coder.com/docs/tutorials/external-database.md): Configure Coder to use an external PostgreSQL database for production deployments.
  - [Image Management](https://coder.com/docs/admin/templates/managing-templates/image-management.md): Learn how to build and manage the container images that back your Coder templates.
  - [Configure custom claims/scopes with Okta for group/role](https://coder.com/docs/tutorials/configuring-okta.md): Configure custom Okta claims and scopes to drive Coder group and role sync.
  - [Persistent shared workspaces with service accounts](https://coder.com/docs/tutorials/persistent-shared-workspaces.md): Set up long-lived shared workspaces with service accounts and workspace sharing
  - [Federate a Google Cloud service account to AWS](https://coder.com/docs/tutorials/gcp-to-aws.md): Federate a Google Cloud service account to AWS so Coder can authenticate across clouds.
  - [JFrog Artifactory integration](https://coder.com/docs/admin/integrations/jfrog-artifactory.md): Integrate Coder with JFrog Artifactory to secure workspaces and manage packages and tokens.
  - [Integrate Coder with Istio](https://coder.com/docs/admin/integrations/istio.md): Use the Istio service mesh to secure and control your Coder workspace traffic.
  - [Island browser integration](https://coder.com/docs/admin/integrations/island.md): Integrate Coder with the Island Enterprise Browser for secure, policy-controlled workspace access.
  - [Define ImagePullSecrets for Coder workspaces](https://coder.com/docs/tutorials/image-pull-secret.md): Create Kubernetes ImagePullSecrets so Coder workspaces can pull images from private registries.
  - [Configure Coder to connect to PostgreSQL using SSL](https://coder.com/docs/tutorials/postgres-ssl.md): Configure Coder to connect to a PostgreSQL database over an encrypted SSL connection.
  - [Federate Coder's control plane to Azure](https://coder.com/docs/tutorials/azure-federation.md): Federate Coder's control plane to Azure so it can authenticate to Azure services.
  - [Deploy Coder on Azure with an Application Gateway](https://coder.com/docs/install/server/kubernetes/kubernetes-azure-app-gateway.md): Deploy Coder on Azure Kubernetes Service behind an Azure Application Gateway ingress controller.
  - [Cloning Git Repositories](https://coder.com/docs/tutorials/cloning-git-repositories.md): Learn how to automatically clone Git repositories into your Coder workspaces on startup.
  - [Test and publish Coder templates through CI/CD](https://coder.com/docs/tutorials/testing-templates.md): Test and publish your Coder templates automatically through a CI/CD pipeline.
  - [How to use Apache as a reverse-proxy with LetsEncrypt](https://coder.com/docs/tutorials/reverse-proxy-apache.md): Configure Apache as a reverse proxy for Coder, with TLS certificates from Let's Encrypt.
  - [Caddy](https://coder.com/docs/tutorials/reverse-proxy-caddy.md): Configure Caddy as a reverse proxy for Coder, with automatic HTTPS certificates.
  - [How to use NGINX as a reverse-proxy with LetsEncrypt](https://coder.com/docs/tutorials/reverse-proxy-nginx.md): Configure NGINX as a reverse proxy for Coder, with TLS certificates from Let's Encrypt.
  - [Pre-install JetBrains IDEs in your template](https://coder.com/docs/admin/templates/extending-templates/jetbrains-preinstall.md): Pre-install JetBrains IDE backends in your template for faster first-time connections.
  - [JetBrains IDEs in an air-gapped environment](https://coder.com/docs/admin/templates/extending-templates/jetbrains-airgapped.md): Configure JetBrains IDEs to work in air-gapped Coder deployments without internet access.
  - [FAQs](https://coder.com/docs/tutorials/faqs.md): Answers to frequently asked questions about Coder OSS and licensed deployments.
  - [Best practices](https://coder.com/docs/tutorials/best-practices.md): Best-practice guides to help you get the most out of your Coder deployment.
    - [Organizations - best practices](https://coder.com/docs/tutorials/best-practices/organizations.md): Best practices for structuring and using Coder organizations effectively.
    - [Scale Coder](https://coder.com/docs/tutorials/best-practices/scale-coder.md): Best practices for preparing and tuning a Coder deployment so it scales to many users.
    - [Security - best practices](https://coder.com/docs/tutorials/best-practices/security-best-practices.md): Follow security best practices to harden your Coder deployment against common risks.
    - [Speed up your Coder templates and workspaces](https://coder.com/docs/tutorials/best-practices/speed-up-templates.md): Speed up Coder template builds and workspace startup with practical optimizations.
- [Reference](https://coder.com/docs/reference.md): Reference for automating Coder through the REST API, command-line interface, and Agent API.
  - [Glossary](https://coder.com/docs/reference/glossary.md): Definitions of Coder terms and product names
  - [Releases](https://coder.com/docs/reference/releases.md): Learn about Coder's release channels, versioning, and schedule so you can plan upgrades.
  - [Feature stages](https://coder.com/docs/reference/feature-stages.md): Understand Coder's feature stages, including early access, beta, and general availability.
  - [REST API](https://coder.com/docs/reference/api.md): Reference for the Coder REST API, including endpoints, authentication, and schemas.
    - [General](https://coder.com/docs/reference/api/general.md)
    - [AI Gateway](https://coder.com/docs/reference/api/aigateway.md)
    - [AI Providers](https://coder.com/docs/reference/api/aiproviders.md)
    - [Agents](https://coder.com/docs/reference/api/agents.md): REST endpoints for the workspace agent daemon (`coder_agent`).
    - [Applications](https://coder.com/docs/reference/api/applications.md)
    - [Audit](https://coder.com/docs/reference/api/audit.md)
    - [Authentication](https://coder.com/docs/reference/api/authentication.md)
    - [Authorization](https://coder.com/docs/reference/api/authorization.md)
    - [Builds](https://coder.com/docs/reference/api/builds.md)
    - [Chats](https://coder.com/docs/reference/api/chats.md): REST endpoints for Coder Agents Chats API (programmatic agent sessions).
    - [Debug](https://coder.com/docs/reference/api/debug.md)
    - [Enterprise](https://coder.com/docs/reference/api/enterprise.md)
    - [Files](https://coder.com/docs/reference/api/files.md)
    - [Git](https://coder.com/docs/reference/api/git.md)
    - [InitScript](https://coder.com/docs/reference/api/initscript.md)
    - [Insights](https://coder.com/docs/reference/api/insights.md)
    - [MCP](https://coder.com/docs/reference/api/mcp.md)
    - [Members](https://coder.com/docs/reference/api/members.md)
    - [Notifications](https://coder.com/docs/reference/api/notifications.md)
    - [Organizations](https://coder.com/docs/reference/api/organizations.md)
    - [PortSharing](https://coder.com/docs/reference/api/portsharing.md)
    - [Prebuilds](https://coder.com/docs/reference/api/prebuilds.md)
    - [Provisioning](https://coder.com/docs/reference/api/provisioning.md)
    - [Schemas](https://coder.com/docs/reference/api/schemas.md)
    - [Secrets](https://coder.com/docs/reference/api/secrets.md)
    - [TemplateBuilder](https://coder.com/docs/reference/api/templatebuilder.md)
    - [Templates](https://coder.com/docs/reference/api/templates.md)
    - [Users](https://coder.com/docs/reference/api/users.md)
    - [WorkspaceProxies](https://coder.com/docs/reference/api/workspaceproxies.md)
    - [Workspaces](https://coder.com/docs/reference/api/workspaces.md)
  - [Command Line](https://coder.com/docs/reference/cli.md): Reference for the Coder command-line interface, with usage and flags for every command.
    - [coder agent-firewall](https://coder.com/docs/reference/cli/agent-firewall.md): Network isolation tool for monitoring and restricting HTTP/HTTPS requests
    - [coder ai-gateway](https://coder.com/docs/reference/cli/ai-gateway.md): Manage AI Gateway
      - [coder ai-gateway keys](https://coder.com/docs/reference/cli/ai-gateway/keys.md): Manage AI Gateway keys
        - [coder ai-gateway keys create](https://coder.com/docs/reference/cli/ai-gateway/keys/create.md): Create an AI Gateway key
        - [coder ai-gateway keys delete](https://coder.com/docs/reference/cli/ai-gateway/keys/delete.md): Delete an AI Gateway key
        - [coder ai-gateway keys list](https://coder.com/docs/reference/cli/ai-gateway/keys/list.md): List AI Gateway keys
      - [coder ai-gateway start](https://coder.com/docs/reference/cli/ai-gateway/start.md): Run a standalone AI Gateway server
    - [coder autoupdate](https://coder.com/docs/reference/cli/autoupdate.md): Toggle auto-update policy for a workspace
    - [coder completion](https://coder.com/docs/reference/cli/completion.md): Install or update shell completion scripts for the detected or chosen shell.
    - [coder config-ssh](https://coder.com/docs/reference/cli/config-ssh.md): Add an SSH Host entry for your workspaces "ssh workspace.coder"
    - [coder create](https://coder.com/docs/reference/cli/create.md): Create a workspace
    - [coder delete](https://coder.com/docs/reference/cli/delete.md): Delete a workspace
    - [coder dotfiles](https://coder.com/docs/reference/cli/dotfiles.md): Personalize your workspace by applying a canonical dotfiles repository
    - [coder external-auth](https://coder.com/docs/reference/cli/external-auth.md): Manage external authentication
      - [coder external-auth access-token](https://coder.com/docs/reference/cli/external-auth/access-token.md): Print auth for an external provider
    - [coder external-workspaces](https://coder.com/docs/reference/cli/external-workspaces.md): Create or manage external workspaces
      - [coder external-workspaces agent-instructions](https://coder.com/docs/reference/cli/external-workspaces/agent-instructions.md): Get the instructions for an external agent
      - [coder external-workspaces create](https://coder.com/docs/reference/cli/external-workspaces/create.md): Create a new external workspace
      - [coder external-workspaces list](https://coder.com/docs/reference/cli/external-workspaces/list.md): List external workspaces
    - [coder favorite](https://coder.com/docs/reference/cli/favorite.md): Add a workspace to your favorites
    - [coder features](https://coder.com/docs/reference/cli/features.md): List Enterprise features
      - [coder features list](https://coder.com/docs/reference/cli/features/list.md)
    - [coder groups](https://coder.com/docs/reference/cli/groups.md): Manage groups
      - [coder groups create](https://coder.com/docs/reference/cli/groups/create.md): Create a user group
      - [coder groups delete](https://coder.com/docs/reference/cli/groups/delete.md): Delete a user group
      - [coder groups edit](https://coder.com/docs/reference/cli/groups/edit.md): Edit a user group
      - [coder groups list](https://coder.com/docs/reference/cli/groups/list.md): List user groups
    - [coder licenses](https://coder.com/docs/reference/cli/licenses.md): Add, delete, and list licenses
      - [coder licenses add](https://coder.com/docs/reference/cli/licenses/add.md): Add license to Coder deployment
      - [coder licenses delete](https://coder.com/docs/reference/cli/licenses/delete.md): Delete license by ID
      - [coder licenses list](https://coder.com/docs/reference/cli/licenses/list.md): List licenses (including expired)
    - [coder list](https://coder.com/docs/reference/cli/list.md): List workspaces
    - [coder login](https://coder.com/docs/reference/cli/login.md): Authenticate with Coder deployment
      - [coder login token](https://coder.com/docs/reference/cli/login/token.md): Print the current session token
    - [coder logout](https://coder.com/docs/reference/cli/logout.md): Unauthenticate your local session
    - [coder logs](https://coder.com/docs/reference/cli/logs.md): View logs for a workspace
    - [coder netcheck](https://coder.com/docs/reference/cli/netcheck.md): Print network debug information for DERP and STUN
    - [coder notifications](https://coder.com/docs/reference/cli/notifications.md): Manage Coder notifications
      - [coder notifications custom](https://coder.com/docs/reference/cli/notifications/custom.md): Send a custom notification
      - [coder notifications pause](https://coder.com/docs/reference/cli/notifications/pause.md): Pause notifications
      - [coder notifications resume](https://coder.com/docs/reference/cli/notifications/resume.md): Resume notifications
      - [coder notifications test](https://coder.com/docs/reference/cli/notifications/test.md): Send a test notification
    - [coder oauth2-provider](https://coder.com/docs/reference/cli/oauth2-provider.md): Manage Coder OAuth2 provider settings
      - [coder oauth2-provider dcr](https://coder.com/docs/reference/cli/oauth2-provider/dcr.md): Manage OAuth2 dynamic client registration (RFC 7591)
        - [coder oauth2-provider dcr disable](https://coder.com/docs/reference/cli/oauth2-provider/dcr/disable.md): Disable OAuth2 dynamic client registration
        - [coder oauth2-provider dcr enable](https://coder.com/docs/reference/cli/oauth2-provider/dcr/enable.md): Enable OAuth2 dynamic client registration
    - [coder open](https://coder.com/docs/reference/cli/open.md): Open a workspace
      - [coder open app](https://coder.com/docs/reference/cli/open/app.md): Open a workspace application.
      - [coder open vscode](https://coder.com/docs/reference/cli/open/vscode.md): Open a workspace in VS Code Desktop
    - [coder organizations](https://coder.com/docs/reference/cli/organizations.md): Organization related commands
      - [coder organizations create](https://coder.com/docs/reference/cli/organizations/create.md): Create a new organization.
      - [coder organizations delete](https://coder.com/docs/reference/cli/organizations/delete.md): Delete an organization
      - [coder organizations edit](https://coder.com/docs/reference/cli/organizations/edit.md): Edit organization settings.
      - [coder organizations list](https://coder.com/docs/reference/cli/organizations/list.md): List all organizations
      - [coder organizations members](https://coder.com/docs/reference/cli/organizations/members.md): Manage organization members
        - [coder organizations members add](https://coder.com/docs/reference/cli/organizations/members/add.md): Add a new member to the current organization
        - [coder organizations members edit-roles](https://coder.com/docs/reference/cli/organizations/members/edit-roles.md): Edit organization member's roles
        - [coder organizations members list](https://coder.com/docs/reference/cli/organizations/members/list.md): List all organization members
        - [coder organizations members remove](https://coder.com/docs/reference/cli/organizations/members/remove.md): Remove a new member to the current organization
      - [coder organizations roles](https://coder.com/docs/reference/cli/organizations/roles.md): Manage organization roles.
        - [coder organizations roles create](https://coder.com/docs/reference/cli/organizations/roles/create.md): Create a new organization custom role
        - [coder organizations roles show](https://coder.com/docs/reference/cli/organizations/roles/show.md): Show role(s)
        - [coder organizations roles update](https://coder.com/docs/reference/cli/organizations/roles/update.md): Update an organization custom role
      - [coder organizations settings](https://coder.com/docs/reference/cli/organizations/settings.md): Manage organization settings.
        - [coder organizations settings set](https://coder.com/docs/reference/cli/organizations/settings/set.md): Update specified organization setting.
          - [coder organizations settings set group-sync](https://coder.com/docs/reference/cli/organizations/settings/set/group-sync.md): Group sync settings to sync groups from an IdP.
          - [coder organizations settings set organization-sync](https://coder.com/docs/reference/cli/organizations/settings/set/organization-sync.md): Organization sync settings to sync organization memberships from an IdP.
          - [coder organizations settings set role-sync](https://coder.com/docs/reference/cli/organizations/settings/set/role-sync.md): Role sync settings to sync organization roles from an IdP.
          - [coder organizations settings set workspace-sharing](https://coder.com/docs/reference/cli/organizations/settings/set/workspace-sharing.md): Workspace sharing settings for the organization.
        - [coder organizations settings show](https://coder.com/docs/reference/cli/organizations/settings/show.md): Outputs specified organization setting.
          - [coder organizations settings show group-sync](https://coder.com/docs/reference/cli/organizations/settings/show/group-sync.md): Group sync settings to sync groups from an IdP.
          - [coder organizations settings show organization-sync](https://coder.com/docs/reference/cli/organizations/settings/show/organization-sync.md): Organization sync settings to sync organization memberships from an IdP.
          - [coder organizations settings show role-sync](https://coder.com/docs/reference/cli/organizations/settings/show/role-sync.md): Role sync settings to sync organization roles from an IdP.
          - [coder organizations settings show workspace-sharing](https://coder.com/docs/reference/cli/organizations/settings/show/workspace-sharing.md): Workspace sharing settings for the organization.
      - [coder organizations show](https://coder.com/docs/reference/cli/organizations/show.md): Show the organization. Using "selected" will show the selected organization from the "--org" flag. Using "me" will show all organizations you are a member of.
    - [coder ping](https://coder.com/docs/reference/cli/ping.md): Ping a workspace
    - [coder port-forward](https://coder.com/docs/reference/cli/port-forward.md): Forward ports from a workspace to the local machine. For reverse port forwarding, use "coder ssh -R".
    - [coder prebuilds](https://coder.com/docs/reference/cli/prebuilds.md): Manage Coder prebuilds
      - [coder prebuilds pause](https://coder.com/docs/reference/cli/prebuilds/pause.md): Pause prebuilds
      - [coder prebuilds resume](https://coder.com/docs/reference/cli/prebuilds/resume.md): Resume prebuilds
    - [coder provisioner](https://coder.com/docs/reference/cli/provisioner.md): View and manage provisioner daemons and jobs
      - [coder provisioner jobs](https://coder.com/docs/reference/cli/provisioner/jobs.md): View and manage provisioner jobs
        - [coder provisioner jobs cancel](https://coder.com/docs/reference/cli/provisioner/jobs/cancel.md): Cancel a provisioner job
        - [coder provisioner jobs list](https://coder.com/docs/reference/cli/provisioner/jobs/list.md): List provisioner jobs
      - [coder provisioner keys](https://coder.com/docs/reference/cli/provisioner/keys.md): Manage provisioner keys
        - [coder provisioner keys create](https://coder.com/docs/reference/cli/provisioner/keys/create.md): Create a new provisioner key
        - [coder provisioner keys delete](https://coder.com/docs/reference/cli/provisioner/keys/delete.md): Delete a provisioner key
        - [coder provisioner keys list](https://coder.com/docs/reference/cli/provisioner/keys/list.md): List provisioner keys in an organization
      - [coder provisioner list](https://coder.com/docs/reference/cli/provisioner/list.md): List provisioner daemons in an organization
      - [coder provisioner start](https://coder.com/docs/reference/cli/provisioner/start.md): Run a provisioner daemon
    - [coder publickey](https://coder.com/docs/reference/cli/publickey.md): Output your Coder public key used for Git operations
    - [coder rename](https://coder.com/docs/reference/cli/rename.md): Rename a workspace
    - [coder reset-password](https://coder.com/docs/reference/cli/reset-password.md): Directly connect to the database to reset a user's password
    - [coder restart](https://coder.com/docs/reference/cli/restart.md): Restart a workspace
    - [coder schedule](https://coder.com/docs/reference/cli/schedule.md): Schedule automated start and stop times for workspaces
      - [coder schedule extend](https://coder.com/docs/reference/cli/schedule/extend.md): Extend the stop time of a currently running workspace instance.
      - [coder schedule show](https://coder.com/docs/reference/cli/schedule/show.md): Show workspace schedules
      - [coder schedule start](https://coder.com/docs/reference/cli/schedule/start.md): Edit workspace start schedule
      - [coder schedule stop](https://coder.com/docs/reference/cli/schedule/stop.md): Edit workspace stop schedule
    - [coder secret](https://coder.com/docs/reference/cli/secret.md): Manage secrets
      - [coder secret create](https://coder.com/docs/reference/cli/secret/create.md): Create a secret
      - [coder secret delete](https://coder.com/docs/reference/cli/secret/delete.md): Delete a secret
      - [coder secret disable](https://coder.com/docs/reference/cli/secret/disable.md): Disable a secret without removing it
      - [coder secret enable](https://coder.com/docs/reference/cli/secret/enable.md): Enable a secret so it is injected into workspaces
      - [coder secret import](https://coder.com/docs/reference/cli/secret/import.md): Import secrets from a file
      - [coder secret list](https://coder.com/docs/reference/cli/secret/list.md): List secrets, or show one by name
      - [coder secret update](https://coder.com/docs/reference/cli/secret/update.md): Update a secret
    - [coder server](https://coder.com/docs/reference/cli/server.md): Start a Coder server
      - [coder server create-admin-user](https://coder.com/docs/reference/cli/server/create-admin-user.md): Create a new admin user with the given username, email and password and adds it to every organization.
      - [coder server dbcrypt](https://coder.com/docs/reference/cli/server/dbcrypt.md): Manage database encryption.
        - [coder server dbcrypt decrypt](https://coder.com/docs/reference/cli/server/dbcrypt/decrypt.md): Decrypt a previously encrypted database.
        - [coder server dbcrypt delete](https://coder.com/docs/reference/cli/server/dbcrypt/delete.md): Delete all encrypted data from the database. THIS IS A DESTRUCTIVE OPERATION.
        - [coder server dbcrypt rotate](https://coder.com/docs/reference/cli/server/dbcrypt/rotate.md): Rotate database encryption keys.
      - [coder server fix-oidc-links](https://coder.com/docs/reference/cli/server/fix-oidc-links.md): Reset OIDC linked IDs that do not match the expected issuer, allowing users to re-authenticate.
      - [coder server postgres-builtin-serve](https://coder.com/docs/reference/cli/server/postgres-builtin-serve.md): Run the built-in PostgreSQL deployment.
      - [coder server postgres-builtin-url](https://coder.com/docs/reference/cli/server/postgres-builtin-url.md): Output the connection URL for the built-in PostgreSQL deployment.
    - [coder show](https://coder.com/docs/reference/cli/show.md): Display details of a workspace's resources and agents
    - [coder speedtest](https://coder.com/docs/reference/cli/speedtest.md): Run upload and download tests from your machine to a workspace
    - [coder ssh](https://coder.com/docs/reference/cli/ssh.md): Start a shell into a workspace or run a command
    - [coder start](https://coder.com/docs/reference/cli/start.md): Start a workspace
    - [coder stat](https://coder.com/docs/reference/cli/stat.md): Show resource usage for the current workspace.
      - [coder stat cpu](https://coder.com/docs/reference/cli/stat/cpu.md): Show CPU usage, in cores.
      - [coder stat disk](https://coder.com/docs/reference/cli/stat/disk.md): Show disk usage, in gigabytes.
      - [coder stat mem](https://coder.com/docs/reference/cli/stat/mem.md): Show memory usage, in gigabytes.
    - [coder state](https://coder.com/docs/reference/cli/state.md): Manually manage Terraform state to fix broken workspaces
      - [coder state pull](https://coder.com/docs/reference/cli/state/pull.md): Pull a Terraform state file from a workspace.
      - [coder state push](https://coder.com/docs/reference/cli/state/push.md): Push a Terraform state file to a workspace.
    - [coder stop](https://coder.com/docs/reference/cli/stop.md): Stop a workspace
    - [coder support](https://coder.com/docs/reference/cli/support.md): Commands for troubleshooting issues with a Coder deployment.
      - [coder support bundle](https://coder.com/docs/reference/cli/support/bundle.md): Generate a support bundle to troubleshoot issues connecting to a workspace.
    - [coder templates](https://coder.com/docs/reference/cli/templates.md): Manage templates
      - [coder templates archive](https://coder.com/docs/reference/cli/templates/archive.md): Archive unused or failed template versions from a given template(s)
      - [coder templates create](https://coder.com/docs/reference/cli/templates/create.md): DEPRECATED: Create a template from the current directory or as specified by flag
      - [coder templates delete](https://coder.com/docs/reference/cli/templates/delete.md): Delete templates
      - [coder templates edit](https://coder.com/docs/reference/cli/templates/edit.md): Edit the metadata of a template by name.
      - [coder templates init](https://coder.com/docs/reference/cli/templates/init.md): Get started with a templated template.
      - [coder templates list](https://coder.com/docs/reference/cli/templates/list.md): List all the templates available for the organization
      - [coder templates presets](https://coder.com/docs/reference/cli/templates/presets.md): Manage presets of the specified template
        - [coder templates presets list](https://coder.com/docs/reference/cli/templates/presets/list.md): List all presets of the specified template. Defaults to the active template version.
      - [coder templates pull](https://coder.com/docs/reference/cli/templates/pull.md): Download the active, latest, or specified version of a template to a path.
      - [coder templates push](https://coder.com/docs/reference/cli/templates/push.md): Create or update a template from the current directory or as specified by flag
      - [coder templates versions](https://coder.com/docs/reference/cli/templates/versions.md): Manage different versions of the specified template
        - [coder templates versions archive](https://coder.com/docs/reference/cli/templates/versions/archive.md): Archive a template version(s).
        - [coder templates versions list](https://coder.com/docs/reference/cli/templates/versions/list.md): List all the versions of the specified template
        - [coder templates versions promote](https://coder.com/docs/reference/cli/templates/versions/promote.md): Promote a template version to active.
        - [coder templates versions unarchive](https://coder.com/docs/reference/cli/templates/versions/unarchive.md): Unarchive a template version(s).
    - [coder tokens](https://coder.com/docs/reference/cli/tokens.md): Manage personal access tokens
      - [coder tokens create](https://coder.com/docs/reference/cli/tokens/create.md): Create a token
      - [coder tokens list](https://coder.com/docs/reference/cli/tokens/list.md): List tokens
      - [coder tokens remove](https://coder.com/docs/reference/cli/tokens/remove.md): Expire or delete a token
      - [coder tokens view](https://coder.com/docs/reference/cli/tokens/view.md): Display detailed information about a token
    - [coder unfavorite](https://coder.com/docs/reference/cli/unfavorite.md): Remove a workspace from your favorites
    - [coder update](https://coder.com/docs/reference/cli/update.md): Will update and start a given workspace if it is out of date. If the workspace is already running, it will be stopped first.
    - [coder users](https://coder.com/docs/reference/cli/users.md): Manage users
      - [coder users activate](https://coder.com/docs/reference/cli/users/activate.md): Update a user's status to 'active'. Active users can fully interact with the platform
      - [coder users create](https://coder.com/docs/reference/cli/users/create.md): Create a new user.
      - [coder users delete](https://coder.com/docs/reference/cli/users/delete.md): Delete a user by username or user_id.
      - [coder users edit-roles](https://coder.com/docs/reference/cli/users/edit-roles.md): Edit a user's roles by username or id
      - [coder users list](https://coder.com/docs/reference/cli/users/list.md): Prints the list of users.
      - [coder users oidc-claims](https://coder.com/docs/reference/cli/users/oidc-claims.md): Display the OIDC claims for the authenticated user.
      - [coder users show](https://coder.com/docs/reference/cli/users/show.md): Show a single user. Use 'me' to indicate the currently authenticated user.
      - [coder users suspend](https://coder.com/docs/reference/cli/users/suspend.md): Update a user's status to 'suspended'. A suspended user cannot log into the platform
    - [coder version](https://coder.com/docs/reference/cli/version.md): Show coder version
    - [coder whoami](https://coder.com/docs/reference/cli/whoami.md): Fetch authenticated user info for Coder deployment
  - [Sections](https://coder.com/docs/reference/agent-api.md): Reference for the Coder Agent API used by workspace agents to communicate with the control plane.
    - [Debug](https://coder.com/docs/reference/agent-api/debug.md)
    - [Schemas](https://coder.com/docs/reference/agent-api/schemas.md)

---

# About

Source: https://coder.com/docs

<!-- Warning for docs contributors: The first route in manifest.json must be titled "About" for the static landing page to work correctly. -->

Coder is a self-hosted platform for running AI coding agents and cloud
development environments on infrastructure you control. It works with any
cloud, IDE, OS, Git provider, and IDP.

![Coder platform showing templates and a running workspace](./images/hero-image.png)

## Coder Workspaces

[Coder Workspaces](./user-guides/index.md) are cloud development environments
defined with Terraform, connected through a secure Wireguard tunnel, and
automatically shut down when not in use. Agents and developers share the same
workspace infrastructure.

- **Defined in Terraform**: Templates describe the infrastructure for each
  workspace, from EC2 VMs and Kubernetes Pods to Docker containers.
- **Any architecture and OS**: Support ARM and x86-64 across Windows, Linux,
  and macOS from a single deployment.
- **Managed by admins**: Platform teams create and maintain templates that
  enforce approved images, resource limits, and security policies.
- **Accessed from any IDE**: Connect through VS Code, JetBrains, Cursor,
  a web terminal, remote desktop, or SSH.
- **Automatic shutdown**: Idle workspaces stop automatically to reduce
  cloud spend, and restart in seconds when needed.

## Coder Agents

[Coder Agents](./ai-coder/agents/index.md) is a native AI coding agent built
into Coder. The agent loop runs in the Coder control plane on your
infrastructure, not in the workspace and not in a vendor's cloud. Developers
interact with agents through the web UI or the REST API for programmatic and
CI-driven workflows.

- **Self-hosted agent loop**: The control plane handles planning, model
  calls, and tool dispatch. Workspaces have zero AI awareness.
- **No API keys in workspaces**: LLM credentials stay in the control plane.
- **Any model**: Anthropic, OpenAI, Google, Bedrock, or self-hosted
  endpoints. Switching is a configuration change.
- **Governance and cost controls**: Centralized model approval, per-user
  spend limits, and audit logging.
- **Open source and inspectable**: The full platform is available to audit
  and extend.

![Coder Agents chat interface with git diff sidebar](./images/agents-hero-image.png)

## IDE support

![IDE icons](./images/ide-icons.svg)

You can use:

- Any Web IDE, such as

  - [code-server](https://github.com/coder/code-server)
  - [JetBrains Projector](https://github.com/JetBrains/projector-server)
  - [Jupyter](https://jupyter.org/)
  - And others

- Your existing remote development environment:

  - [JetBrains Gateway](https://www.jetbrains.com/remote-development/gateway/)
  - [VS Code Remote](https://code.visualstudio.com/docs/remote/ssh-tutorial)
  - [Emacs](./user-guides/workspace-access/emacs-tramp.md)

- A file sync such as [Mutagen](https://mutagen.io/)

## Why remote development

Provisioning consistent development environments for a large engineering team
is difficult. Each developer has preferences for operating systems, editors,
and toolchains, and ensuring a reliable build environment across all of them
is a maintenance burden. A missed step during onboarding or an unsupported
local configuration can cost hours of debugging.

Remote development solves this by moving the environment off the developer's
machine and into managed infrastructure. The developer's laptop becomes a
portal into the actual compute where work happens. If a device is lost or
replaced, access is simply revoked; no source code or credentials are stored
locally.

This approach provides:

- **Speed**: Server-grade hardware accelerates builds, tests, and large
  workloads without requiring expensive local machines.
- **Consistency**: Infrastructure tools such as Terraform, nix, Docker, and
  Dev Containers produce identical environments for every developer.
- **Security**: Source code stays on private servers. Users and groups are
  managed through [SSO](./admin/users/oidc-auth/index.md) and
  [RBAC](./admin/users/groups-roles.md#roles).
- **Compatibility**: Workspaces share infrastructure configurations with
  staging and production, reducing configuration drift.
- **Accessibility**: Browser-based IDEs and remote IDE extensions let
  developers work from any device, including lightweight laptops,
  Chromebooks, and tablets.

Read more on the [Coder blog](https://coder.com/blog), the
[Slack engineering blog](https://slack.engineering/development-environments-at-slack),
or from [Alex Ellis at OpenFaaS](https://blog.alexellis.io/the-internet-is-my-computer/).

## Why Coder

The key difference between Coder and other platforms is that the entire system,
agent loop, control plane, model routing, and workspace provisioning, runs on
infrastructure you control.

For agents, this means platform teams can:

- Run the entire agent loop on their infrastructure, with no SaaS
  dependency for orchestration.
- Define MCP servers, skills, and system prompts centrally so every agent
  session starts with the same tools, policies, and context.
- Keep LLM credentials out of workspaces entirely.
- Tie every agent action to an authenticated user identity.
- Support air-gapped and restricted-network deployments with self-hosted models.

For workspaces, this means admins can:

- Support any architecture (ARM, x86-64) and operating system
  (Windows, Linux, macOS).
- Modify pod/container specs, such as adding disks, managing network policies, or
  setting/updating environment variables.
- Use VM or dedicated workspaces, developing with Kernel features (no container
  knowledge required).
- Enable persistent workspaces, which are like local machines, but faster and
  hosted by a cloud service.

## Pricing

Coder is free and open source under the
[GNU Affero General Public License v3.0](../LICENSE).
All developer productivity features are included in the open source version.
A [Premium license](https://coder.com/pricing#compare-plans) is available for
enhanced support and custom deployments.

## How Coder works

Coder workspaces are represented with Terraform, but you do not need to know
Terraform to get started. The
[Coder Registry](https://registry.coder.com/templates) provides production-ready
templates for AWS EC2, Azure, Google Cloud, Kubernetes, and other providers.

![Providers and compute environments](./images/providers-compute.png)_Providers and compute environments_

Workspaces can include more than just compute. Terraform can add storage
buckets, secrets, sidecars, and
[other resources](https://developer.hashicorp.com/terraform/tutorials).

See the [templates documentation](./admin/templates/index.md) for details.

## What Coder is not

- Coder is not an infrastructure as code (IaC) platform.

  - Terraform is the first IaC _provisioner_ in Coder, allowing Coder admins to
    define Terraform resources as Coder workspaces.

- Coder is not a DevOps/CI platform.

  - Coder workspaces can be configured to follow best practices for
    cloud-service-based workloads, but Coder is not responsible for how you
    define or deploy the software you write.

- Coder is not an online IDE.

  - Coder supports common editors, such as VS Code, vim, and JetBrains,
    all over HTTPS or SSH.

- Coder is not a collaboration platform.

  - You can use Git with your favorite Git platform and dedicated IDE
    extensions for pull requests, code reviews, and pair programming.

- Coder is not a SaaS/fully-managed offering.
  - Coder is a [self-hosted](<https://en.wikipedia.org/wiki/Self-hosting_(web_services)>)
    solution.
    You must host Coder in a private data center or on a cloud service, such as
    AWS, Azure, or GCP.

## Learn more

- [Coder Agents](./ai-coder/agents/index.md)
- [Templates](./admin/templates/index.md)
- [Installing Coder](./install/index.md)
- [Quickstart tutorial](./get-started/index.md)

---

# Screenshots

Source: https://coder.com/docs/about/screenshots

## Log in

![Install Coder in your cloud or air-gapped on-premises. Developers simply log in via their browser to access their Workspaces.](../images/screenshots/coder-login.png)

Install Coder in your cloud or air-gapped on-premises. Developers simply log in
via their browser to access their Workspaces.

## Templates

![Developers provision their own ephemeral Workspaces in minutes using pre-defined Templates that include approved tooling and infrastructure.](../images/screenshots/templates-listing.png)

Developers provision their own ephemeral Workspaces in minutes using pre-defined
Templates that include approved tooling and infrastructure.

![Template administrators create templates using the template builder, which guides them through selecting base infrastructure and adding modules.](../images/templatebuilder_01_bases.png)

Template administrators create templates using the template builder, which
guides them through selecting base infrastructure and adding modules. Templates
can also be created from scratch or uploaded directly.

![Templates define the underlying infrastructure that Coder Workspaces run on.](../images/screenshots/terraform.png)

Template administrators build Templates using Terraform. Templates define the
underlying infrastructure that Coder Workspaces run on.

## Workspaces

![Developers create and delete their own workspaces. Coder administrators can easily enforce Workspace scheduling and autostop policies to ensure idle Workspaces don’t burn unnecessary cloud budget.](../images/screenshots/workspaces-listing.png)

Developers create and delete their own workspaces. Coder administrators can
easily enforce Workspace scheduling and autostop policies to ensure idle
Workspaces don’t burn unnecessary cloud budget.

![Developers launch their favorite web-based or desktop IDE, browse files, or access their Workspace’s Terminal.](../images/screenshots/workspace-running-with-topbar.png)

Developers launch their favorite web-based or desktop IDE, browse files, or
access their Workspace’s Terminal.

## Administration

![Coder administrators can access Template usage insights to understand which Templates are most popular and how well they perform for developers.](../images/screenshots/template-insights.png)

Coder administrators can access Template usage insights to understand which
Templates are most popular and how well they perform for developers.

![Coder administrators can control *every* aspect of their Coder deployment.](../images/screenshots/admin-settings.png)

Coder administrators can control *every* aspect of their Coder deployment.

![Coder administrators and auditor roles can review how users are interacting with their Coder Workspaces and Templates.](../images/screenshots/audit.png)

Coder administrators and auditor roles can review how users are interacting with
their Coder Workspaces and Templates.

![Coder administrators can monitor the health of their Coder deployment, including database latency, active provisioners, and more.](../images/screenshots/healthcheck.png)

Coder administrators can monitor the health of their Coder deployment, including
database latency, active provisioners, and more.

---

# Support

Source: https://coder.com/docs/support

If you have questions, encounter an issue or bug, or if you have a feature request, [open a GitHub issue](https://github.com/coder/coder/issues/new) or [join our Discord](https://discord.gg/coder).

<children></children>

---

# Generate and upload a support bundle to Coder Support

Source: https://coder.com/docs/support/support-bundle

When you engage with Coder support to diagnose an issue with your deployment,
you may be asked to generate and upload a "Support Bundle" for offline analysis.
This document explains the contents of a support bundle and the steps to submit
a support bundle to Coder staff.

## What is a Support Bundle?

A support bundle is an archive containing a snapshot of information about your
Coder deployment.

It contains information about the workspace, the template it uses, running
agents in the workspace, and other detailed information useful for
troubleshooting.

It is primarily intended for troubleshooting connectivity issues to workspaces,
but can be useful for diagnosing other issues as well.

**While we attempt to redact sensitive information from support bundles, they
may contain information deemed sensitive by your organization and should be
treated as such.**

A brief overview of all files contained in the bundle is provided below:

> [!NOTE]
> Detailed descriptions of all the information available in the bundle is
> out of scope, as support bundles are primarily intended for internal use.

| Filename                                      | Description                                                                                                                                                                            |
|-----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent/agent.json`                            | The agent used to connect to the workspace with environment variables stripped.                                                                                                        |
| `agent/agent_magicsock.html`                  | The contents of the HTTP debug endpoint of the agent's Tailscale Wireguard connection.                                                                                                 |
| `agent/client_magicsock.html`                 | The contents of the HTTP debug endpoint of the client's Tailscale Wireguard connection.                                                                                                |
| `agent/listening_ports.json`                  | The listening ports detected by the selected agent running in the workspace.                                                                                                           |
| `agent/logs.txt`                              | Active agent log plus rotated agent logs modified in the last 24&nbsp;hours, capped at 100&nbsp;MiB.                                                                                   |
| `agent/workspace_files/collection_errors.txt` | Workspace file entries dropped while assembling the bundle, such as entries exceeding the size budget. Only present when entries were dropped.                                         |
| `agent/workspace_files/files/`                | Files collected from inside the remote workspace with `--workspace-file`. Only present when workspace paths are requested.                                                             |
| `agent/workspace_files/manifest.json`         | Describes the remote workspace file collection: requested patterns, collected files, per-path errors, truncation, and applied limits. Only present when workspace paths are requested. |
| `agent/manifest.json`                         | The manifest of the selected agent with environment variables stripped.                                                                                                                |
| `agent/startup_logs.txt`                      | Startup logs of the workspace agent.                                                                                                                                                   |
| `agent/prometheus.txt`                        | The contents of the agent's Prometheus endpoint.                                                                                                                                       |
| `cli_logs.txt`                                | Logs from running the `coder support bundle` command.                                                                                                                                  |
| `deployment/buildinfo.json`                   | Coder version and build information.                                                                                                                                                   |
| `deployment/config.json`                      | Deployment [configuration](../reference/api/general.md#get-deployment-config), with secret values removed. *Requires Owner role.*                                                      |
| `deployment/experiments.json`                 | Any [experiments](../reference/cli/server/index.md#--experiments) currently enabled for the deployment.                                                                                |
| `deployment/health.json`                      | A snapshot of the [health status](../admin/monitoring/health-check.md) of the deployment. *Requires Owner role.*                                                                       |
| `logs.txt`                                    | Logs from the `codersdk.Client` used to generate the bundle.                                                                                                                           |
| `network/connection_info.json`                | Information used by workspace agents used to connect to Coder (DERP map etc.)                                                                                                          |
| `network/coordinator_debug.html`              | Peers currently connected to each Coder instance and the tunnels established between peers. *Requires Owner role.*                                                                     |
| `network/netcheck.json`                       | Results of running `coder netcheck` locally.                                                                                                                                           |
| `network/tailnet_debug.html`                  | Tailnet coordinators, their heartbeat ages, connected peers, and tunnels. *Requires Owner role.*                                                                                       |
| `workspace/build_logs.txt`                    | Build logs of the selected workspace.                                                                                                                                                  |
| `workspace/workspace.json`                    | Details of the selected workspace.                                                                                                                                                     |
| `workspace/parameters.json`                   | Build parameters of the selected workspace.                                                                                                                                            |
| `workspace/template.json`                     | The template currently in use by the selected workspace.                                                                                                                               |
| `workspace/template_file.zip`                 | The source code of the template currently in use by the selected workspace.                                                                                                            |
| `workspace/template_version.json`             | The template version currently in use by the selected workspace.                                                                                                                       |
| `vscode-logs/`                                | Only present when generated from the VS Code Coder Remote extension. Includes logs, redacted settings, and local telemetry files.                                                      |

## How do I generate a Support Bundle?

1. Ensure your deployment is up and running. Generating a support bundle
   requires the Coder deployment to be available.

2. Ensure you have the Coder CLI installed on a local machine. See
   [installation](../install/index.md) for steps on how to do this.

   > [!NOTE]
   > It is recommended to generate a support bundle from a location
   > experiencing workspace connectivity issues.

3. Ensure you are [logged in](../reference/cli/login/index.md) to your Coder
   deployment. Any authenticated user can generate a support bundle. Users with
   the Owner role will get the most complete bundle; non-admin users will still
   get a useful bundle but some admin-only data will be omitted (see the note
   below).

4. Run `coder support bundle [owner/workspace]`, and respond `yes` to the
   prompt. The support bundle will be generated in the current directory with
   the filename `coder-support-$TIMESTAMP.zip`.

   If you use VS Code, you can also run **Coder: Create Support Bundle** from
   the Command Palette. The VS Code Coder Remote extension runs
   `coder support bundle` and appends recent VS Code diagnostics to the
   generated archive. Bundles created with the CLI alone do not include
   `vscode-logs/`. Learn more about
   [VS Code diagnostics](../user-guides/workspace-access/vscode.md#diagnostics-and-support-bundles).

   > [!NOTE]
   > While support bundles can be generated without a running workspace, it is
   > recommended to specify one to maximize troubleshooting information.

   To collect workspace-side files such as editor or service logs, add one
   `--workspace-file` flag for each path or glob. This is explicit
   opt-in. The CLI sends each value to the workspace agent, so quote globs to
   prevent your local shell from expanding them:

   ```sh
   coder support bundle my-workspace \
     --workspace-file '$HOME/.vscode-server/data/logs/**/*.log' \
     --workspace-file '$HOME/.local/share/code-server/coder-logs/**/*.log'
   ```

   Workspace paths and globs are evaluated by the workspace agent.
   Environment variables such as `$HOME` expand in the workspace, and `~/` resolves against the agent user's home directory; any absolute path in the workspace can be requested.
   Symlinks are followed for directly requested paths, but not during glob traversal.
   Collection is limited to 10000 files and 100&nbsp;MiB in total; files larger than 10&nbsp;MiB are truncated to their last 10&nbsp;MiB and marked as truncated in the manifest.
   Collected files are stored under `agent/workspace_files/files/`, and collection metadata is stored in `agent/workspace_files/manifest.json`.

   > [!WARNING]
   > Workspace files can contain tokens, credentials, source code, or other
   > sensitive data. Extract and review `agent/workspace_files/` before sharing
   > the bundle.

5. (Recommended) Extract the support bundle and review its contents, redacting
   any information you deem necessary.

6. Coder staff will provide you a link where you can upload the bundle along
   with any other necessary supporting files.

   > [!NOTE]
   > It is helpful to leave an informative message regarding the nature of
   > supporting files.

Coder support will then review the information you provided and respond to you
with next steps.

---

# Quickstart

Source: https://coder.com/docs/get-started

Follow this guide to get your first Coder development environment running in under 10&nbsp;minutes.
This guide covers the essential concepts and shows you how to create your first workspace and open it in your preferred editor.
This workspace includes a basic set of tools to edit most code bases.

## What you'll do

In this quickstart, you'll:

- ✅ Install the Coder control plane.
- ✅ Create a **template** (blueprint for dev environments).
- ✅ Launch a **workspace** (your actual dev environment).
- ✅ Connect from your favorite IDE.

## A 30-second metaphor for Coder

Before diving in, the following table breaks down the core concepts that power Coder,
explained through a cooking analogy:

| Component      | What It Is                                                                           | Real-World Analogy             |
|----------------|--------------------------------------------------------------------------------------|--------------------------------|
| **You**        | The engineer/developer/builder working                                               | The head chef cooking the meal |
| **Templates**  | A Terraform blueprint that defines your dev environment (OS, tools, resources)       | Recipe for a meal              |
| **Workspaces** | The actual running environment created from the template                             | The cooked meal                |
| **Users**      | A developer who launches the workspace from a template and does their work inside it | The people eating the meal     |

**Putting it Together:** Coder separates who _defines_ environments from who _uses_ them. Admins create and manage Templates, the recipes, while developers use those Templates to launch Workspaces, the meals.

## Prerequisites

- A machine with 2+ CPU cores and 4&nbsp;GB+ RAM (ideally a separate machine or VM, not your primary dev machine)
- Familiarity with running commands in the terminal
- 10&nbsp;minutes of your time

<details>
<summary>Why a separate machine?</summary>

Coder's value comes from remote development.
Hosting the control plane on a separate machine, such as a cloud VM, a spare desktop, or on-premises hardware, gives you and your team infrastructure that's more powerful, always-on, and reachable from anywhere, instead of tying your dev environment to your own laptop.

When you're ready to move past this tutorial, install the control plane on a separate machine and connect to it remotely.
Refer to the [Install guide](../install/index.md) for supported platforms and installation methods.

</details>

> [!TIP]
> If you use a coding agent like Claude Code, the [coder/skills](https://github.com/coder/skills) `setup` skill can train the coding agent on the following steps (install a container runtime, install Coder, create your first template, and launch a workspace).

## Step 1: Install a container runtime

Coder needs a Docker-compatible container runtime running on the host, such as
[Colima](https://colima.run), [Rancher Desktop](https://rancherdesktop.io),
[Podman](https://podman.io), or
[Docker Desktop](https://www.docker.com/products/docker-desktop/). If you
already have one installed and running, skip ahead to
[Step 2](#step-2-install-and-start-coder). Otherwise, follow the steps below to
install a free runtime quickly on your platform.

<div class="tabs">

### Linux

1. Install Docker Engine:

   ```sh
   curl -sSL https://get.docker.com | sh
   ```

   For more details, visit [Docker's docs on installing Docker on Linux](https://docs.docker.com/desktop/install/linux-install/).

1. Assign your user to the Docker group:

   ```sh
   sudo usermod -aG docker $USER
   ```

1. Run `newgrp` to activate the groups changes:

   ```sh
   newgrp docker
   ```

   You might need to log out of and back into your machine or restart your
   machine for changes to take effect.

1. Launch the Docker daemon:

   ```sh
   sudo systemctl start docker
   ```

### macOS

[Colima](https://colima.run) is a free, lightweight container runtime that
provides the Docker daemon on macOS without the overhead of Docker Desktop.

1. Install Colima and the Docker CLI with [Homebrew](https://brew.sh):

   ```sh
   brew install colima docker
   ```

1. Start Colima to launch the Docker daemon:

   ```sh
   colima start
   ```

1. Point `DOCKER_HOST` at the Colima socket so Coder can reach the daemon:

   ```sh
   export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
   ```

   Colima exposes its Docker socket at `~/.colima/default/docker.sock`, not `/var/run/docker.sock`, so Coder needs `DOCKER_HOST` to find it.
   Set it in the same terminal where you'll run `coder server` in the next step.
   To persist it across new terminals and restarts, add the `export` line to your shell's startup file, such as `~/.zshrc`, `~/.bashrc`, or `~/.config/fish/config.fish`.

### Windows

If you plan to use the built-in PostgreSQL database, ensure that the
[Visual C++ Runtime](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist#latest-microsoft-visual-c-redistributable-version)
is installed.

[Podman Desktop](https://podman-desktop.io) is a free GUI for the Podman container runtime.
Its onboarding installs and configures the required
Windows Subsystem for Linux (WSL2) or Hyper-V layer if it isn't already enabled.

1. Download and install [Podman Desktop](https://podman-desktop.io/downloads).

1. Follow the onboarding to configure Podman.

1. If you configured Podman to use WSL2, then you will need to do either
   upgrade WSL2 to version 2.5.1 or later
   (which uses [cgroups](https://wikipedia.org/wiki/Cgroups) v2 by default)
   or create a `.wslconfig` file in the `%USERPROFILE%` directory
   with the following contents

   ```txt
   [wsl2]
   kernelCommandLine=cgroup_no_v1=all
   ```

   This is not required for Podman with Hyper-V.

1. Open Podman Desktop and complete the onboarding to create and start a
   Podman machine.

   Podman Desktop enables Docker socket compatibility by default, so tools
   that expect the Docker daemon work without additional configuration.

</div>

## Step 2: Install and start Coder

Install the `coder` CLI to get started:

<div class="tabs">

### Linux/macOS

1. Install Coder:

   ```sh
   curl -fsSL https://coder.com/install.sh | sh
   ```

   - For standalone binaries, system packages, or other alternate installation
     methods, refer to the
     [latest release on GitHub](https://github.com/coder/coder/releases/latest).

1. Start Coder:

   ```sh
   coder server
   ```

### Windows

If you plan to use the built-in PostgreSQL database, ensure that the
[Visual C++ Runtime](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist#latest-microsoft-visual-c-redistributable-version)
is installed.

1. Use the
   [`winget`](https://learn.microsoft.com/en-us/windows/package-manager/winget/#use-winget)
   package manager to install Coder:

   ```ps1
   winget install Coder.Coder
   ```

1. Start Coder:

   ```sh
   coder server
   ```

</div>

Coder will attempt to open the setup page in your browser. If it doesn't open
automatically, go to <http://localhost:3000>.

- If you get a browser warning similar to `Secure Site Not Available`, you can
  ignore the warning and continue to the setup page.

If your control plane is on a network or cloud device, or you are having trouble
viewing the page, locate the web UI URL in Coder logs in your terminal. It looks
like `https://<CUSTOM-STRING>.<TUNNEL>.try.coder.app`. It's one of the first
lines of output, so you might have to scroll up to find it.

This section includes some of the quicker ways to install Coder. For more detailed options, visit the [Install](../install/index.md) page.

## Step 3: Initial setup

1. Create your admin account:
   - Email: `your.email@example.com`
   - Password: Choose a strong password.

   You can also choose to **Continue with GitHub** instead of creating an admin
   account. Coder automatically grants admin permissions to the first user that signs in.

   ![Welcome to Coder - Create admin user](../images/screenshots/welcome-create-admin-user.png)

## Step 4: Create your first template and workspace

> [!TIP]
> If you use an AI coding assistant, the [coder-templates](https://github.com/coder/registry/blob/main/.agents/skills/coder-templates/SKILL.md) agent skill can guide you through creating and customizing templates with best practices built-in.

Templates define what's in your development environment. The template builder
guides you through creating one without writing any Terraform.

1. Coder opens the template builder after initial setup.
   To open it again later, select **Templates** > **New Template**.

1. Select the **Docker** base template from the list.

   > [!NOTE]
   > This template requires Docker to be running in the background, so make sure Docker is running.

1. Skip or configure any base template parameters, then select modules to add
   IDEs and tools to your template. For example, add **code-server** to get
   VS Code in the browser. You can skip module selection for now and add
   modules later.

1. On the final step, name your template:
   - **Name**: `my-docker-template`
   - **Display name** and **Description**: fill in as you like.

1. Select **Create Template**. Coder composes and validates the Terraform
   configuration, then creates your template.

   ![Template builder base selection step](../images/templatebuilder_01_bases.png)

**What just happened?**
The template builder selected a base infrastructure template, composed it with
any modules you chose, and generated a valid Terraform configuration. Coder
validated the configuration server-side, then created a reusable template in
your organization's template list. You and any teammates in the same
organization can now create workspaces from it.

<details>
<summary>What happens under the hood?</summary>

A Coder template is a [Terraform](https://developer.hashicorp.com/terraform/intro) configuration, and Coder is built on top of Terraform.
When you create a workspace from this template, a Coder [provisioner](../install/plan/architecture.md#provisionerd) runs a Terraform job from the template's configuration to build your environment.
For the Docker base template, that job starts a Docker container with the Coder agent pre-configured, along with any modules you selected.

To learn how Coder uses Terraform to provision and run workspaces, refer to the [architecture overview](../install/plan/architecture.md).

</details>

Now it's time to launch a workspace.

## Step 5: Launch your workspace

1. After the template is ready, select **+ Create Workspace**.

1. Give the workspace a name. If you need a suggestion, you can select the
   automatically generated name next to the **Need a suggestion?** label.

1. If the template has any
   [parameters](../admin/templates/extending-templates/parameters.md), fill
   them in. Parameters vary by template and the modules you selected in the
   builder.

1. Select **Create workspace**.

After a short wait (10-15&nbsp;seconds on most modern computers), Coder will start your new workspace:

![getting-started-workspace is running](../images/screenshots/workspace-running-with-topbar.png)_Workspace is running_

## Step 6: Connect your IDE

Each button in the workspace view is a different **agent app**.
The buttons in the UI reflect the modules you added in the template builder (such as code-server, Claude Code, or any of the JetBrains editors).
Select your preferred IDE from the list of agent apps.

This guide uses **VS Code Desktop**, which opens the workspace in the VS Code installed on your local machine, using the Coder extension.
To stay in the browser instead, select the browser-based VS Code option.
The remaining steps are similar for other IDEs and editors.

After VS Code loads the remote environment, you can select **Open Folder** to
explore directories in the Docker container or work on something new.

![Changing directories in VS Code](../images/screenshots/change-directory-vscode.png)

If you didn't clone an existing Git repository when you created your
workspace, you can clone it manually if you want:

1. Select **Clone Repository** and enter the repository URL.

   For example, to clone the Coder repo, enter
   `https://github.com/coder/coder.git`.

   Learn more about how to find the repository URL in the
   [GitHub documentation](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository).

2. Choose the folder to which VS Code should clone the repo. It will be in its
   own directory within this folder.

   Note that you cannot create a new parent directory in this step.

3. After VS Code completes the clone, select **Open** to open the directory.

4. You are now using VS Code in your Coder environment!

## What's next?

You now have:

- A control plane running locally.
- A template defining your environment.
- A workspace running that environment.
- IDE access to code remotely.

Now that you have your own workspace running, you can [customize your template](./customize-your-template/index.md) to fit your needs.

## Learn more

- [Try Coder Agents](../ai-coder/agents/getting-started.md), the chat
  interface and API for delegating development work to coding agents in your
  Coder deployment.

- [Read about managing Workspaces for your team](../user-guides/workspace-management.md)

- [Read about implementing monitoring tools for your Coder Deployment](../admin/monitoring/index.md)

## Troubleshooting

### Cannot connect to the Docker daemon

When creating a workspace from a Docker template, you may see an error like:

```txt
Error: Error pinging Docker server: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

This usually means a container runtime is either not installed or not running on the machine where Coder is running.
A runtime must be running before you create a workspace from a Docker-based template.

If the runtime is running but Coder still cannot connect, the daemon may expose its socket at a path other than `/var/run/docker.sock`.
This is common with Colima on macOS and with rootless Docker on Linux.
In that case, point Coder at the socket with the `DOCKER_HOST` environment variable, then restart the control plane.

<div class="tabs">

#### Linux

1. Install Docker, if you haven't already:

   ```sh
   curl -sSL https://get.docker.com | sh
   ```

1. Start the Docker daemon:

   ```sh
   sudo systemctl start docker
   ```

1. Assign your user to the `docker` group so Coder can access the daemon
   without root:

   ```sh
   sudo usermod -aG docker $USER
   newgrp docker
   ```

1. Confirm the group membership:

   ```console
   $ groups
   docker sudo users
   ```

#### macOS

1. If Colima is not installed, install it with [Homebrew](https://brew.sh):

   ```sh
   brew install colima docker
   ```

1. Start Colima to launch the Docker daemon:

   ```sh
   colima start
   ```

1. Verify that the daemon is reachable:

   ```sh
   docker ps
   ```

1. If `docker ps` works but Coder still cannot connect, point `DOCKER_HOST` at the Colima socket, then restart the control plane:

   ```sh
   export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
   ```

   To persist the setting across restarts, add that `export` line to your shell's startup file, such as `~/.zshrc`, `~/.bashrc`, or `~/.config/fish/config.fish`.

#### Windows

1. If Podman Desktop is not installed,
   [download and install it](https://podman-desktop.io/downloads).

1. Open Podman Desktop and verify that a Podman machine is running.

</div>

### Can't start `coder server`: Address already in use

```txt
Encountered an error running "coder server", see "coder server --help" for more information
error: configure http(s): listen tcp 127.0.0.1:3000: bind: address already in use
```

Another process is already listening on port 3000. Identify and stop it,
then start the control plane again.

<div class="tabs">

#### Linux

1. Stop the process:

   ```sh
   sudo systemctl stop coder
   ```

1. Start Coder:

   ```sh
   coder server
   ```

#### macOS

1. Identify the process using port 3000:

   ```sh
   lsof -i :3000
   ```

1. Stop the process using the PID from the previous command:

   ```sh
   kill <PID>
   ```

   If the process does not exit, force-kill it:

   ```sh
   kill -9 <PID>
   ```

1. Start Coder:

   ```sh
   coder server
   ```

#### Windows

1. Identify the process using port 3000 in PowerShell:

   ```ps1
   Get-NetTCPConnection -LocalPort 3000 | Select-Object OwningProcess
   ```

1. Stop the process using the PID from the previous command:

   ```ps1
   Stop-Process -Id <PID>
   ```

1. Start Coder:

   ```sh
   coder server
   ```

</div>

---

# Customize your template

Source: https://coder.com/docs/get-started/customize-your-template

In [Launch your first workspace](../index.md), you installed the `coder` CLI, started the control plane, and built a workspace from the Quickstart template.
That template is a good starting point, but it has gaps:

- It may not include every language in which you write code.
- It comes with a base toolset, but not the personal command-line tools you install on every machine.
- It clones public repositories, but it can't reach your private repositories without manual authentication.

This part of the Quickstart closes those gaps one at a time.
Most of these guides edit the same template and introduce one Terraform building block.
One guide instead works inside a running workspace.
Each guide ties its change to something you can observe.

## What you'll do

Work through the guides in order, or pick the one that solves your problem:

- [Add a programming language](./add-a-language.md): expose a new language through a parameter and install it at startup.
- [Install your own command-line tools](./install-command-line-tools.md): install personal command-line tools and make them persist.
- [Clone private repositories](./authenticate-to-github.md): authenticate to GitHub with an external-auth data source.

Each guide takes about 10&nbsp;minutes.

## Templates in brief

A template is a [Terraform](https://developer.hashicorp.com/terraform) blueprint for a workspace.
It consists of one or more Terraform files (`*.tf`), and it can include templated scripts (`*.tftpl`), a `README`, and any other supporting file.

Every Coder template declares the `coder` provider inside a `required_providers` block:

```tf
terraform {
  required_providers {
    coder = {
      source = "coder/coder"
    }
  }
}
```

A template is built from a few kinds of Terraform block:

- A [provider](https://developer.hashicorp.com/terraform/language/providers) is a plugin that connects Terraform to a platform or service.
  The `coder` provider connects Terraform to Coder.
- A [resource](https://developer.hashicorp.com/terraform/language/resources) is any infrastructure object you want to manage with Terraform, such as a workspace agent or a cloud storage bucket.
- A [data source](https://developer.hashicorp.com/terraform/language/data-sources) reads data from a provider without creating or changing infrastructure.
  Parameters and external auth are data sources.
- A [module](https://developer.hashicorp.com/terraform/language/modules) is a reusable bundle of resources, data sources, providers, and other Terraform blocks you pull in by reference.
  Modules reduce the need to define the same Terraform code multiple times.
  You can pull modules from the [Coder Registry](https://registry.coder.com).

To go deeper on any of these, visit the [Terraform documentation](https://developer.hashicorp.com/terraform).

## Open the template for editing

Most guides in this part edit the Quickstart template.
Open it for editing now, either in the Coder web editor or in your local editor with the `coder` CLI.

<div class="tabs">

### UI

1. Log in to Coder and select **Templates**.
2. Find the **Coder Quickstart** template you created and open it.
3. Select the three-dots menu next to **Create Workspace**, then select **Edit files**.

The template web editor opens:

![Coder template web editor](../../images/screenshots/template-web-editor.png)_Coder template web editor_

### CLI

Pull the template to your local filesystem so you can edit it in your own editor.
With the control plane running in your existing terminal, open a second terminal and log in:

```sh
coder login
```

`coder login` opens a browser page that generates a session token.
Copy the token, return to the terminal, and paste it.
Then pull the template:

```sh
coder templates pull quickstart ~/coder-quickstart
```

Open the `~/coder-quickstart` folder in your preferred editor.

</div>

The template has 3 files:

- `install-languages.sh.tftpl`, a startup script that installs the selected languages.
- `main.tf`, the Terraform that defines the workspace.
- `README.md`.

The guides in this part edit `main.tf` and `install-languages.sh.tftpl`.

Each guide publishes a new template version after you edit these files.
The guides use the CLI command `coder templates push`, which reads from the `~/coder-quickstart` folder you pulled.
If you opened the template in the web editor instead, publish the new version from the editor each time a guide tells you to push.

## What's next?

Start with [Add a programming language](./add-a-language.md), then work through the rest of the series in order.

## Learn more

- [Extending templates](../../admin/templates/extending-templates/index.md) in the Coder documentation
- [Terraform documentation](https://developer.hashicorp.com/terraform) from HashiCorp

---

# Add a programming language to your template

Source: https://coder.com/docs/get-started/customize-your-template/add-a-language

Now that you've finished [Launch your first workspace](../index.md), you can add another language toolchain to every workspace you create.

The Quickstart template installs a language only when the workspace owner selects it from the **Programming Languages** parameter.
In this guide, you add Ruby as an option.

> [!NOTE]
> This guide assumes your Quickstart template is open for editing.
> If it's not, you can edit the template from the web by finding the template, selecting the three dots menu, and selecting **Edit files**.
> Refer to [Customize workspace startup](./index.md#open-the-template-for-editing) for more information.

## What you'll do

- ✅ Add a Ruby option to the **Programming Languages** parameter.
- ✅ Publish the change and apply it to your running workspace.
- ✅ Install the Ruby toolchain so selecting Ruby works.

## Parameters in brief

A parameter is a question Coder asks when someone creates a workspace.
Each parameter comes from a `coder_parameter` [data source](https://developer.hashicorp.com/terraform/language/data-sources) in the template.
The **Programming Languages** parameter is a multi-select list, and each language the reader can choose is an `option` block:

```tf
data "coder_parameter" "languages" {
  name         = "languages"
  display_name = "Programming Languages"
  description  = "Select the languages to pre-install in your workspace"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(["python"])
  mutable      = true
  icon         = "/icon/code.svg"
  order        = 1

  option {
    name  = "Python"
    value = "python"
    icon  = "/icon/python.svg"
  }
  # ...more options
}
```

This produces the following dropdown parameter:

![Programming Language dropdown parameter from the Quickstart template](../../images/screenshots/quickstart-language-param.png)_Programming Language dropdown parameter from the Quickstart template_

Adding an `option` adds a choice to that list.

## Step 1: Add the Ruby option

In `main.tf`, find the `data "coder_parameter" "languages"` block.
Add a Ruby `option` after the last existing option, before the parameter's closing brace:

```tf
  option {
    name  = "Ruby"
    value = "ruby"
    icon  = "/icon/ruby.svg"
  }
```

> [!IMPORTANT]
> The `option` block must sit at the same indentation as the other `option` blocks inside the parameter.
> Coder reads the parameter's choices from these blocks, so a misplaced `option` doesn't appear in the form.

The `icon` value points at an icon bundled with your Coder deployment.
To browse the full set and copy a path, open `https://<your-coder-url>/icons`.

Now publish the change as a new template version:

<div class="tabs">

### UI

In the web editor, make the edit above in `main.tf`.
Select **Build**, wait for the build to pass, then select **Publish**.

### CLI

Make the edit in `~/coder-quickstart/main.tf`, then publish a new version:

```sh
coder templates push -d ~/coder-quickstart -y quickstart
```

</div>

## Step 2: Add Ruby to your workspace

Your workspace from [Launch your first workspace](../index.md) is still on the old template version.
Update it to the version you just published, and add Ruby to its **Programming Languages** selection:

<div class="tabs">

### UI

1. From your workspace, open **Workspace settings** (top right), then select **Parameters**.
2. Add **Ruby** to the **Programming Languages** parameter.
3. Apply the change. Coder updates the workspace to the new template version and restarts it with Ruby selected.

### CLI

Update the workspace and re-select its parameters.
Replace `<your-workspace>` with your workspace's name (run `coder list` to see it):

```sh
coder update <your-workspace> --always-prompt
```

When prompted for **Programming Languages**, add **Ruby**, then let the workspace rebuild.

</div>

Adding the Ruby option to the parameter shows the following:

![Programming Language dropdown parameter from the Quickstart template with Ruby](../../images/screenshots/quickstart-language-param-ruby.png)_Programming Language dropdown parameter from the Quickstart template with Ruby_

## Step 3: Check whether Ruby is installed

When the workspace restarts, open a terminal and ask for the Ruby version:

```sh
ruby --version
```

The command fails:

```txt
ruby: command not found
```

You added the option, selected it, and rebuilt the workspace, but Ruby isn't there.
Adding the `option` only changed the form.
It added Ruby to the list of choices, but nothing in the template acts on that choice yet.
A separate startup script installs each selected toolchain, and you haven't taught it about Ruby.

## Step 4: Install Ruby when the workspace starts

The template installs each selected language from `install-languages.sh.tftpl`, a startup script that runs when the workspace boots.
Open that file and add a branch that installs Ruby when the reader selects it:

```sh
if echo "$LANGUAGES" | grep -q "ruby"; then
  if command -v ruby >/dev/null 2>&1; then
    echo "Ruby: $(ruby --version | head -1)"
  else
    echo "Installing Ruby toolchain..."
    apt_update
    sudo apt-get install -y -qq ruby-full
    echo "Installed Ruby: $(ruby --version | head -1)"
  fi
fi
```

The script installs Ruby with `apt-get`, the package manager built into the workspace image.

> [!WARNING]
> Use the package manager the workspace image provides, not a personal one.
> If you replace the `apt-get` line with `brew install ruby`, the build fails: the `codercom/example-base:ubuntu` image doesn't include Homebrew, so the workspace logs `brew: command not found` and Ruby never installs.
> To install a personal tool like a Homebrew formula in your own workspace, refer to [Install your own command-line tools](./install-command-line-tools.md).

Publish the change, then update your workspace again:

<div class="tabs">

### UI

1. In the web editor, make the edit above in `install-languages.sh.tftpl`.
2. Select **Build**, wait for the build to pass, then select **Publish**.
3. On your workspace's home tab, select **Update and restart**.

### CLI

Make the edit in `~/coder-quickstart/install-languages.sh.tftpl`, then publish and update:

```sh
coder templates push -d ~/coder-quickstart -y quickstart
coder update <your-workspace>
```

</div>

Ruby is already selected, so you don't change parameters this time.
When the workspace restarts, open a terminal and check again:

```sh
ruby --version
```

This time the workspace reports a Ruby version.

## Step 5: Add a Ruby preset

Steps 1 through 4 make Ruby selectable as a parameter and install it at startup.
The Quickstart template also ships presets: named bundles of parameter values that appear on the workspace creation form:

![Default presets with the Quickstart template](../../images/screenshots/quickstart-default-presets.png)_Default presets with the Quickstart template_

The shipped presets cover combinations like Go and Python, but none selects Ruby, so add one to keep the parameter and preset choices in sync.

In `main.tf`, find the `# --- Presets ---` section and add a Ruby preset next to the existing ones:

```tf
data "coder_workspace_preset" "ruby_dev" {
  name = "Ruby Development"
  icon = "/icon/ruby.svg"
  parameters = {
    languages      = jsonencode(["ruby"])
    ides           = jsonencode(["code-server", "jetbrains"])
    jetbrains_ides = jsonencode(["RM"])
    git_repo       = ""
  }
}
```

This preset adds JetBrains RubyMine as a default option for the language, but you can customize the preferred IDEs in this default based on your needs.

Publish the template again.
The next time you create a workspace, **Ruby Development** appears in the preset list and preselects Ruby:

![Updated presets with the Quickstart template](../../images/screenshots/quickstart-updated-presets.png)_Updated presets with the Quickstart template_

Expanding the preset parameters after selecting **Ruby Development** shows the parameter values Coder will use to create the workspace:

![Expanded parameter values for the Ruby Development preset](../../images/screenshots/quickstart-ruby-preset.png)_Expanded parameter values for the Ruby Development preset_

## What just happened

You changed two different things to add one language:

- The `coder_parameter` `option` block added Ruby to the workspace creation form.
- The startup script installed the Ruby toolchain when a workspace owner selected Ruby.

A parameter collects a choice.
A startup script acts on it.
A new language needs both.

You also added support for a new preset, so workspace users can launch a workspace from this template quickly, without having to fill out the parameters manually.

<details>
<summary>How does Coder install the language you pick?</summary>

The selection travels through the template in four steps:

1. The `option` block in `data "coder_parameter" "languages"` (`main.tf`) adds `ruby` to the values the form accepts.
2. When the workspace builds, `local.languages` decodes the selection in `main.tf`:

   ```tf
   languages = jsondecode(data.coder_parameter.languages.value)
   ```

3. `coder_script.install_languages` renders the startup script with that list and runs it on the agent (also in `main.tf`):

   ```tf
   script = templatefile("${path.module}/install-languages.sh.tftpl", {
     LANGUAGES = join(",", local.languages)
   })
   ```

4. Inside the rendered script, the `ruby` branch matches and installs the toolchain:

   ```sh
   if echo "$LANGUAGES" | grep -q "ruby"; then
   ```

The first three steps ran as soon as you added the option, which is why Ruby appeared in the form.
Step 4 is the part you were missing in Step 3, so the script had nothing to do for `ruby`.

</details>

<details>
<summary>Why a <code>.tftpl</code> file instead of a plain script?</summary>

The install script needs to know which languages the workspace owner selected, and only Terraform has that value when the workspace builds.
`templatefile()` renders `install-languages.sh.tftpl` and replaces `${LANGUAGES}` with `join(",", local.languages)`, producing a finished script with the selection baked in.
A static `.sh` file couldn't receive that value, so the `.tftpl` is the bridge between the parameter and the shell script.

</details>

## Final code

<details>

<summary>The complete template files</summary>

Your template files after this guide's changes, starting from the Quickstart template:

<div class="tabs">

### main.tf

```tf
terraform {
  required_providers {
    coder = {
      source = "coder/coder"
    }
    docker = {
      source = "kreuzwerker/docker"
    }
    external = {
      source = "hashicorp/external"
    }
  }
}

variable "docker_socket" {
  default     = ""
  description = "(Optional) Docker socket URI"
  type        = string
}

provider "docker" {
  host = var.docker_socket != "" ? var.docker_socket : null
}

data "coder_provisioner" "me" {}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}

# --- Parameters ---

data "coder_parameter" "languages" {
  name         = "languages"
  display_name = "Programming Languages"
  description  = "Select the languages to pre-install in your workspace"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(["python"])
  mutable      = true
  icon         = "/icon/code.svg"
  order        = 1

  option {
    name  = "Python"
    value = "python"
    icon  = "/icon/python.svg"
  }
  option {
    name  = "Node.js"
    value = "nodejs"
    icon  = "/icon/nodejs.svg"
  }
  option {
    name  = "Go"
    value = "go"
    icon  = "/icon/go.svg"
  }
  option {
    name  = "Rust"
    value = "rust"
    icon  = "/icon/rust.svg"
  }
  option {
    name  = "Java"
    value = "java"
    icon  = "/icon/java.svg"
  }
  option {
    name  = "C/C++"
    value = "cpp"
    icon  = "/icon/cpp.svg"
  }
  option {
    name  = "Ruby"
    value = "ruby"
    icon  = "/icon/ruby.svg"
  }
}

data "coder_parameter" "ides" {
  name         = "ides"
  display_name = "IDEs & Editors"
  description  = "Select the development environments for your workspace"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(["code-server"])
  mutable      = true
  icon         = "/icon/code.svg"
  order        = 2

  option {
    name  = "VS Code (Browser)"
    value = "code-server"
    icon  = "/icon/code.svg"
  }
  option {
    name  = "Cursor"
    value = "cursor"
    icon  = "/icon/cursor.svg"
  }
  option {
    name  = "JetBrains IDEs"
    value = "jetbrains"
    icon  = "/icon/jetbrains.svg"
  }
  option {
    name  = "Zed"
    value = "zed"
    icon  = "/icon/zed.svg"
  }
  option {
    name  = "Devin Desktop"
    value = "devin-desktop"
    icon  = "/icon/devin.svg"
  }
}

# Shown only when "JetBrains IDEs" is selected in the IDEs parameter.
# Pre-selects IDEs that match the chosen languages.
data "coder_parameter" "jetbrains_ides" {
  count        = contains(local.ides, "jetbrains") ? 1 : 0
  name         = "jetbrains_ides"
  display_name = "JetBrains IDEs"
  description  = "Select the JetBrains IDEs to install"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(local.jetbrains_ides_from_languages)
  mutable      = true
  icon         = "/icon/jetbrains.svg"
  order        = 3

  option {
    name  = "IntelliJ IDEA"
    value = "IU"
    icon  = "/icon/intellij.svg"
  }
  option {
    name  = "PyCharm"
    value = "PY"
    icon  = "/icon/pycharm.svg"
  }
  option {
    name  = "GoLand"
    value = "GO"
    icon  = "/icon/goland.svg"
  }
  option {
    name  = "WebStorm"
    value = "WS"
    icon  = "/icon/webstorm.svg"
  }
  option {
    name  = "RustRover"
    value = "RR"
    icon  = "/icon/rustrover.svg"
  }
  option {
    name  = "CLion"
    value = "CL"
    icon  = "/icon/clion.svg"
  }
  option {
    name  = "PhpStorm"
    value = "PS"
    icon  = "/icon/phpstorm.svg"
  }
  option {
    name  = "RubyMine"
    value = "RM"
    icon  = "/icon/rubymine.svg"
  }
  option {
    name  = "Rider"
    value = "RD"
    icon  = "/icon/rider.svg"
  }
}

data "coder_parameter" "git_repo" {
  name         = "git_repo"
  display_name = "Git Repository (Optional)"
  description  = "URL of a Git repository to clone into your workspace (leave empty to skip)"
  type         = "string"
  default      = ""
  mutable      = true
  icon         = "/icon/git.svg"
  order        = 4
}

# --- Locals ---

locals {
  username  = data.coder_workspace_owner.me.name
  languages = jsondecode(data.coder_parameter.languages.value)
  ides      = jsondecode(data.coder_parameter.ides.value)

  # Map selected languages to the relevant JetBrains IDE product codes.
  # Used as the default for the JetBrains IDE selector parameter.
  jetbrains_by_language = {
    python = ["PY"]
    go     = ["GO"]
    java   = ["IU"]
    nodejs = ["WS"]
    rust   = ["RR"]
    cpp    = ["CL"]
  }
  jetbrains_ides_from_languages = distinct(flatten([
    for lang in local.languages : lookup(local.jetbrains_by_language, lang, [])
  ]))

  # The actual JetBrains IDEs to install, from the user's selection
  # in the conditional JetBrains parameter (or empty if not shown).
  jetbrains_selected = contains(local.ides, "jetbrains") ? jsondecode(data.coder_parameter.jetbrains_ides[0].value) : []
}

# --- Agent ---

resource "coder_agent" "main" {
  arch           = data.coder_provisioner.me.arch
  os             = "linux"
  startup_script = <<-EOT
    set -e
    if [ ! -f ~/.init_done ]; then
      cp -rT /etc/skel ~
      touch ~/.init_done
    fi
  EOT

  env = {
    GIT_AUTHOR_NAME     = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
    GIT_AUTHOR_EMAIL    = "${data.coder_workspace_owner.me.email}"
    GIT_COMMITTER_NAME  = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
    GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
  }

  metadata {
    display_name = "CPU Usage"
    key          = "0_cpu_usage"
    script       = "coder stat cpu"
    interval     = 10
    timeout      = 1
  }

  metadata {
    display_name = "RAM Usage"
    key          = "1_ram_usage"
    script       = "coder stat mem"
    interval     = 10
    timeout      = 1
  }

  metadata {
    display_name = "Home Disk"
    key          = "3_home_disk"
    script       = "coder stat disk --path $${HOME}"
    interval     = 60
    timeout      = 1
  }
}

# --- Language installation ---
# All languages install in a single script to avoid apt-get lock
# conflicts (coder_script resources run in parallel).

resource "coder_script" "install_languages" {
  count              = length(local.languages) > 0 ? 1 : 0
  agent_id           = coder_agent.main.id
  display_name       = "Install Languages"
  icon               = "/icon/code.svg"
  run_on_start       = true
  start_blocks_login = true
  script = templatefile("${path.module}/install-languages.sh.tftpl", {
    LANGUAGES = join(",", local.languages)
  })
}

# --- IDE modules ---

module "code-server" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "code-server") ? 1 : 0)
  source   = "registry.coder.com/coder/code-server/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  order    = 1
}

module "cursor" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "cursor") ? 1 : 0)
  source   = "registry.coder.com/coder/cursor/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 3
}

# TODO: Re-add the coder/jetbrains module once Coder's dynamic
# parameter system respects module count for parameter visibility.
# The module's internal coder_parameter appears even when count = 0,
# creating a ghost parameter in the workspace creation form.
# module "jetbrains" {
#   count    = data.coder_workspace.me.start_count * (contains(local.ides, "jetbrains") && length(local.jetbrains_selected) > 0 ? 1 : 0)
#   source   = "registry.coder.com/coder/jetbrains/coder"
#   version  = "~> 1.0"
#   agent_id = coder_agent.main.id
#   folder   = "/home/coder"
#   default  = toset(local.jetbrains_selected)
# }

module "zed" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "zed") ? 1 : 0)
  source   = "registry.coder.com/coder/zed/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 5
}

module "devin-desktop" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "devin-desktop") ? 1 : 0)
  source   = "registry.coder.com/coder/devin-desktop/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 6
}

# --- Git clone ---

module "git-clone" {
  count    = data.coder_workspace.me.start_count * (data.coder_parameter.git_repo.value != "" ? 1 : 0)
  source   = "registry.coder.com/coder/git-clone/coder"
  version  = "~> 2.0"
  agent_id = coder_agent.main.id
  url      = data.coder_parameter.git_repo.value
}

# --- Presets ---

data "coder_workspace_preset" "web_dev" {
  name = "Web Development"
  icon = "/icon/nodejs.svg"
  parameters = {
    languages = jsonencode(["python", "nodejs"])
    ides      = jsonencode(["code-server"])
    git_repo  = ""
  }
}

data "coder_workspace_preset" "backend_go" {
  name = "Backend (Go)"
  icon = "/icon/go.svg"
  parameters = {
    languages      = jsonencode(["go"])
    ides           = jsonencode(["code-server", "jetbrains"])
    jetbrains_ides = jsonencode(["GO"])
    git_repo       = ""
  }
}

data "coder_workspace_preset" "data_science" {
  name = "Data Science"
  icon = "/icon/python.svg"
  parameters = {
    languages = jsonencode(["python"])
    ides      = jsonencode(["code-server"])
    git_repo  = ""
  }
}

data "coder_workspace_preset" "full_stack" {
  name = "Full Stack"
  icon = "/icon/code.svg"
  parameters = {
    languages = jsonencode(["python", "nodejs", "go"])
    ides      = jsonencode(["code-server", "cursor"])
    git_repo  = ""
  }
}

data "coder_workspace_preset" "ruby_dev" {
  name = "Ruby Development"
  icon = "/icon/ruby.svg"
  parameters = {
    languages      = jsonencode(["ruby"])
    ides           = jsonencode(["code-server", "jetbrains"])
    jetbrains_ides = jsonencode(["RM"])
    git_repo       = ""
  }
}

# --- Docker resources ---

resource "docker_volume" "home_volume" {
  name = "coder-${data.coder_workspace.me.id}-home"
  lifecycle {
    ignore_changes = all
  }
  labels {
    label = "coder.owner"
    value = data.coder_workspace_owner.me.name
  }
  labels {
    label = "coder.owner_id"
    value = data.coder_workspace_owner.me.id
  }
  labels {
    label = "coder.workspace_id"
    value = data.coder_workspace.me.id
  }
  labels {
    label = "coder.workspace_name_at_creation"
    value = data.coder_workspace.me.name
  }
  depends_on = []
}

resource "docker_container" "workspace" {
  count    = data.coder_workspace.me.start_count
  image    = "codercom/example-base:ubuntu"
  name     = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
  hostname = data.coder_workspace.me.name
  entrypoint = [
    "sh", "-c",
    replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal"),
  ]
  env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
  host {
    host = "host.docker.internal"
    ip   = "host-gateway"
  }
  volumes {
    container_path = "/home/coder"
    volume_name    = docker_volume.home_volume.name
    read_only      = false
  }
  labels {
    label = "coder.owner"
    value = data.coder_workspace_owner.me.name
  }
  labels {
    label = "coder.owner_id"
    value = data.coder_workspace_owner.me.id
  }
  labels {
    label = "coder.workspace_id"
    value = data.coder_workspace.me.id
  }
  labels {
    label = "coder.workspace_name"
    value = data.coder_workspace.me.name
  }
  depends_on = []
}
```

### install-languages.sh.tftpl

```sh
#!/bin/bash
set -e

LANGUAGES="${LANGUAGES}"
APT_UPDATED=false

apt_update() {
  if [ "$APT_UPDATED" = "false" ]; then
    sudo apt-get update -qq
    APT_UPDATED=true
  fi
}

if echo "$LANGUAGES" | grep -q "python"; then
  if command -v python3 >/dev/null 2>&1; then
    echo "Python: $(python3 --version)"
  else
    echo "Installing Python..."
    apt_update
    sudo apt-get install -y -qq python3 python3-pip python3-venv
    echo "Installed Python: $(python3 --version)"
  fi
fi

if echo "$LANGUAGES" | grep -q "nodejs"; then
  if command -v node >/dev/null 2>&1; then
    echo "Node.js: $(node --version)"
  else
    echo "Installing Node.js 22..."
    curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
    sudo apt-get install -y -qq nodejs
    echo "Installed Node.js: $(node --version)"
  fi
fi

if echo "$LANGUAGES" | grep -q "go"; then
  if command -v /usr/local/go/bin/go >/dev/null 2>&1; then
    echo "Go: $(/usr/local/go/bin/go version)"
  else
    echo "Installing Go..."
    ARCH=$(uname -m)
    case $ARCH in
      x86_64)  GOARCH="amd64" ;;
      aarch64) GOARCH="arm64" ;;
      *)       echo "Unsupported architecture: $ARCH"; exit 1 ;;
    esac
    GO_VERSION=$(curl -fsSL "https://go.dev/VERSION?m=text" | head -1)
    curl -fsSL "https://go.dev/dl/$${GO_VERSION}.linux-$${GOARCH}.tar.gz" | sudo tar -C /usr/local -xz
    echo 'export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin' | sudo tee /etc/profile.d/go.sh >/dev/null
    echo "Installed Go: $(/usr/local/go/bin/go version)"
  fi
fi

if echo "$LANGUAGES" | grep -q "rust"; then
  if command -v rustc >/dev/null 2>&1 || [ -f "$HOME/.cargo/bin/rustc" ]; then
    RUSTC=$${HOME}/.cargo/bin/rustc
    command -v rustc >/dev/null 2>&1 && RUSTC=rustc
    echo "Rust: $($RUSTC --version)"
  else
    echo "Installing Rust..."
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
    echo "Installed Rust: $($HOME/.cargo/bin/rustc --version)"
  fi
fi

if echo "$LANGUAGES" | grep -q "java"; then
  if command -v java >/dev/null 2>&1; then
    echo "Java: $(java --version 2>&1 | head -1)"
  else
    echo "Installing Java (OpenJDK 21)..."
    apt_update
    sudo apt-get install -y -qq openjdk-21-jdk
    echo "Installed Java: $(java --version 2>&1 | head -1)"
  fi
fi

if echo "$LANGUAGES" | grep -q "cpp"; then
  if command -v gcc >/dev/null 2>&1; then
    echo "C/C++: $(gcc --version | head -1)"
  else
    echo "Installing C/C++ toolchain..."
    apt_update
    sudo apt-get install -y -qq gcc g++ make cmake
    echo "Installed C/C++: $(gcc --version | head -1)"
  fi
fi

if echo "$LANGUAGES" | grep -q "ruby"; then
  if command -v ruby >/dev/null 2>&1; then
    echo "Ruby: $(ruby --version | head -1)"
  else
    echo "Installing Ruby toolchain..."
    apt_update
    sudo apt-get install -y -qq ruby-full
    echo "Installed Ruby: $(ruby --version | head -1)"
  fi
fi

echo "Language setup complete."
```

</div>

</details>

## What's next?

Now that you added a language, you can [install your own command-line tools](./install-command-line-tools.md).

## Learn more

- [Parameters](../../admin/templates/extending-templates/parameters.md) in the Coder documentation
- [Terraform data sources](https://developer.hashicorp.com/terraform/language/data-sources)
- [Terraform types](https://developer.hashicorp.com/terraform/language/expressions/types) for parameter values

---

# Install your own command-line tools

Source: https://coder.com/docs/get-started/customize-your-template/install-command-line-tools

Now that you [launched your first workspace](../index.md), you can add your favorite command-line tools to every workspace.

The Quickstart template installs system languages through the **Programming Languages** parameter, but it doesn't carry the small command-line tools you may often use, such as [`bat`](https://github.com/sharkdp/bat) or [`ripgrep`](https://github.com/BurntSushi/ripgrep).
You can install those yourself with a package manager like [Homebrew](https://brew.sh/) or [mise](https://mise.jdx.dev/).

In this guide, you install both Homebrew and mise, install a tool with each, and learn which installs survive a workspace restart and why.
You then change the template so the Homebrew tools persist too, and finish by making your tools install in every new workspace automatically.

> [!NOTE]
> This guide works inside a running workspace from the Quickstart template.
> Most of it runs in the workspace, but the last two steps edit the template so Homebrew persists and every new workspace ships with your tools.

## What you'll do

- ✅ Install command-line tools with [Homebrew](https://brew.sh/) and [mise](https://mise.jdx.dev/) into your workspace.
- ✅ Restart the workspace and see which tools persist.
- ✅ Learn why one persists and the other doesn't.
- ✅ Wire up Homebrew so its tools persist too.
- ✅ Preinstall your tools in every new workspace from the template.

## What persists in a workspace

A Quickstart workspace keeps your home directory, `/home/coder`, on a persistent volume.
Everything outside `/home/coder` comes from the workspace image, and Coder rebuilds it from that image every time the workspace starts.

A tool survives a restart only when both of these are true:

- The tool installs into `/home/coder`.
- Your shell finds the tool through a file in `/home/coder`, such as `.bashrc`.

You'll install tools two ways and restart to see this rule decide which ones stay, change the template so Homebrew follows the rule too, then preinstall your tools in every new workspace.

## Step 1: Install Homebrew and mise

Open a terminal in your workspace.

Install [Homebrew](https://brew.sh/) with its setup script:

```sh
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

Homebrew installs to `/home/linuxbrew/.linuxbrew`.
Add it to your shell so the `brew` command is available:

```sh
echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> ~/.bashrc
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
```

Confirm Homebrew is available before you continue:

```sh
brew --version
```

Install [mise](https://mise.jdx.dev/) with its setup script:

```sh
curl -fsSL https://mise.run | sh
```

mise installs to `~/.local/bin/mise`, inside your home directory.
Activate it so every new shell loads it:

```sh
echo 'eval "$(~/.local/bin/mise activate bash)"' >> ~/.bashrc
```

Activation only takes effect in shells that start after this change, so open a new terminal (or run `source ~/.bashrc`) before you use mise.
Until you do, `mise doctor` reports that mise isn't activated, which is expected at this point.
For other shells, refer to [Activate mise](https://mise.jdx.dev/getting-started.html#activate-mise).

Open a new terminal so both the Homebrew and mise changes take effect, then confirm each manager runs:

```sh
brew --version
mise --version
```

> [!NOTE]
> If you manage `~/.bashrc` with [dotfiles](../../user-guides/workspace-dotfiles.md), add the `brew shellenv` and `mise activate` lines to the `.bashrc` in your dotfiles repository instead, so applying your dotfiles doesn't overwrite them.

## Step 2: Install a tool with each manager

Install [`ripgrep`](https://github.com/BurntSushi/ripgrep) with Homebrew:

```sh
brew install ripgrep
```

Install [`bat`](https://github.com/sharkdp/bat) with mise:

```sh
mise use -g bat
```

Confirm both tools run:

```sh
rg --version
bat --version
```

Both work.
So far, the two package managers look interchangeable.

## Step 3: Restart the workspace and compare

Restart the workspace.
The restart rebuilds the container from the image and keeps only your home directory.

<div class="tabs">

### UI

Open your workspace in the Coder dashboard and select **Restart**.
When it's back, reconnect by reopening the web terminal.

### CLI

From a terminal on your own machine, restart the workspace by name, then reconnect when it's back:

```sh
coder restart <your-workspace>
coder ssh <your-workspace>
```

</div>

When you reconnect, your shell prints an error before you run anything:

```txt
bash: /home/linuxbrew/.linuxbrew/bin/brew: No such file or directory
```

That's the first sign something changed.
Your `.bashrc` still tries to load Homebrew, but the restart removed it.
Check each tool to see what survived.

`bat`, installed with mise, still works:

```sh
bat --version
```

```txt
bat 0.26.1
```

`rg`, installed with Homebrew, is gone:

```sh
rg --version
```

```txt
bash: rg: command not found
```

So is `brew` itself:

```sh
brew --version
```

```txt
bash: brew: command not found
```

mise installed `bat` under `/home/coder`, which persists, so `bat` survived.
Homebrew installed `ripgrep` to `/home/linuxbrew`, outside `/home/coder`, so the rebuild discarded Homebrew and every formula you installed with it.
The `brew shellenv` line stayed in your `.bashrc` because it lives in `/home/coder`, which is why your shell still tries to load the missing `brew` and prints the error above.

## Step 4: Make Homebrew survive restarts

To make Homebrew survive a restart, you'll edit the template and add a persistent volume.
The volume backs `/home/linuxbrew`, the prefix where Homebrew installs, so Homebrew and its formulae stay between restarts.

> [!NOTE]
> This step assumes your Quickstart template is open for editing.
> If it's not, you can edit the template from the web by finding the template, selecting the three dots menu, and selecting **Edit files**.
> Refer to [Customize workspace startup](./index.md#open-the-template-for-editing) for more information.

In `main.tf`, add a volume for Homebrew's directory next to the existing `home_volume`:

```tf
resource "docker_volume" "homebrew_volume" {
  name = "coder-${data.coder_workspace.me.id}-homebrew"
  lifecycle {
    ignore_changes = all
  }
}
```

Then mount it in the `docker_container "workspace"` resource, alongside the block that mounts `/home/coder`:

```tf
  volumes {
    container_path = "/home/linuxbrew"
    volume_name    = docker_volume.homebrew_volume.name
    read_only      = false
  }
```

Publish the change and restart the workspace:

<div class="tabs">

### UI

In the web editor, make the edits above in `main.tf`.
Select **Build**, wait for the build to pass, then select **Publish**.
On your workspace's home tab, select **Update and restart**.

### CLI

Make the edits in `~/coder-quickstart/main.tf`, then publish and update by name:

```sh
coder templates push -d ~/coder-quickstart -y quickstart
coder update <your-workspace>
```

</div>

The restart gives you a persistent but empty `/home/linuxbrew`.
Your earlier Homebrew install is gone, so install it once more.
This time it lands on the volume:

```sh
NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

The `brew shellenv` line is still in your `.bashrc` from Step 1, so open a new terminal to load it, then reinstall `ripgrep`:

```sh
brew install ripgrep
```

Restart the workspace once more and reconnect.
This time the startup error is gone, and both tools report their versions:

```sh
rg --version
brew --version
```

Homebrew now persists because `/home/linuxbrew` lives on its own volume, the same way mise's tools persist because they live in `/home/coder`.

## Step 5: Install your tools in every new workspace

Steps 1 through 4 set up your tools in this workspace.
To give everyone who uses the template the same tools, install them from the template so every new workspace starts with them.

The template already installs languages on every start with the `install_languages` script.
You'll add a second script that installs your command-line tools the same way.

> [!NOTE]
> This step edits the template.
> If it isn't open for editing, refer to [Customize workspace startup](./index.md#open-the-template-for-editing).

mise is the lighter choice here.
It installs prebuilt binaries into `/home/coder`, which already persists, so the first start stays quick and later starts reuse the tools.

In `main.tf`, add a script next to the existing `install_languages` resource:

```tf
resource "coder_script" "install_tools" {
  agent_id     = coder_agent.main.id
  display_name = "Install Tools"
  icon         = "/icon/terminal.svg"
  run_on_start = true
  script       = <<-EOT
    #!/usr/bin/env bash
    set -e

    # Install mise on first start. It lives in /home/coder, so later starts reuse it.
    if [ ! -x "$HOME/.local/bin/mise" ]; then
      curl -fsSL https://mise.run | sh
    fi
    export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"

    # Install the tools for everyone who uses the template, tracking the latest release.
    mise use -g ripgrep@latest bat@latest

    # Load mise in new interactive shells so the tools are on PATH.
    if ! grep -qs 'mise activate' "$HOME/.bashrc"; then
      echo 'eval "$(mise activate bash)"' >> "$HOME/.bashrc"
    fi
  EOT
}
```

`mise use -g ripgrep@latest bat@latest` writes the tools to mise's global config at `~/.config/mise/config.toml` and installs them, so every workspace from the template resolves the same versions.

Publish the change and apply it to your workspace:

<div class="tabs">

### UI

In the web editor, add the `install_tools` resource to `main.tf`.
Select **Build**, wait for the build to pass, then select **Publish**.
On your workspace's home tab, select **Update and restart**.

### CLI

Add the resource in `~/coder-quickstart/main.tf`, then publish and update by name:

```sh
coder templates push -d ~/coder-quickstart -y quickstart
coder update <your-workspace>
```

</div>

When the workspace is back, confirm both tools run without installing anything by hand:

```sh
rg --version
bat --version
```

The script runs on every start, so every new workspace from the template now ships with `ripgrep` and `bat`.

<details>

<summary>Use Homebrew and a Brewfile instead</summary>

If you'd rather manage these tools with Homebrew, install them from a [Brewfile](https://docs.brew.sh/Brew-Bundle-and-Brewfile) on every start.
This approach relies on the `/home/linuxbrew` volume you added in Step 4, so Homebrew and its formulae persist between restarts.

Use this `install_tools` script in place of the mise version:

```tf
resource "coder_script" "install_tools" {
  agent_id     = coder_agent.main.id
  display_name = "Install Tools"
  icon         = "/icon/terminal.svg"
  run_on_start = true
  script       = <<-EOT
    #!/usr/bin/env bash
    set -e

    # Install Homebrew on first start, while the volume is still empty.
    if [ ! -x /home/linuxbrew/.linuxbrew/bin/brew ]; then
      NONINTERACTIVE=1 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    fi
    eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"

    # Write a Brewfile and install everything it lists.
    printf 'brew "ripgrep"\nbrew "bat"\n' > "$HOME/Brewfile"
    brew bundle install --file="$HOME/Brewfile"

    # Load Homebrew in new shells so the tools are on PATH.
    if ! grep -qs 'brew shellenv' "$HOME/.bashrc"; then
      echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' >> "$HOME/.bashrc"
    fi
  EOT
}
```

Homebrew installs more slowly than mise on a fresh volume because it downloads larger packages, which is why mise is the default here.

</details>

## What just happened

The two package managers behaved differently for one reason: where each one installs.

- mise installs into `~/.local/share/mise`, inside your home directory, and activates from `~/.bashrc`.
  Both are in `/home/coder`, so its tools persist with no template change.
- Homebrew installs to `/home/linuxbrew`, outside `/home/coder`, so its tools are discarded on every restart until you mount that path on a persistent volume.

To keep a tool, choose the approach that matches who needs it:

- For a tool that's yours alone, install it with mise.
  It persists through restarts with no template change.
- To keep your Homebrew tools, mount `/home/linuxbrew` on a persistent volume, as you did in Step 4.
  This is a template change, so it affects everyone who uses the template.
- To preinstall a tool in every new workspace, add it to the template's startup script, as you did in Step 5 with mise.
  You can also install system packages with `apt-get`, as in [Add a programming language](./add-a-language.md), or bake the tool into the workspace image.

The rule underneath all of these: a tool persists when it lives in a part of the workspace that persists.
Refer to [Resource persistence](../../admin/templates/extending-templates/resource-persistence.md) for how Coder decides what survives a restart.

## Final code

<details>

<summary>The complete <code>main.tf</code></summary>

Your `main.tf` after this guide's changes, starting from the Quickstart template:

```tf
terraform {
  required_providers {
    coder = {
      source = "coder/coder"
    }
    docker = {
      source = "kreuzwerker/docker"
    }
    external = {
      source = "hashicorp/external"
    }
  }
}

variable "docker_socket" {
  default     = ""
  description = "(Optional) Docker socket URI"
  type        = string
}

provider "docker" {
  host = var.docker_socket != "" ? var.docker_socket : null
}

data "coder_provisioner" "me" {}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}

# --- Parameters ---

data "coder_parameter" "languages" {
  name         = "languages"
  display_name = "Programming Languages"
  description  = "Select the languages to pre-install in your workspace"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(["python"])
  mutable      = true
  icon         = "/icon/code.svg"
  order        = 1

  option {
    name  = "Python"
    value = "python"
    icon  = "/icon/python.svg"
  }
  option {
    name  = "Node.js"
    value = "nodejs"
    icon  = "/icon/nodejs.svg"
  }
  option {
    name  = "Go"
    value = "go"
    icon  = "/icon/go.svg"
  }
  option {
    name  = "Rust"
    value = "rust"
    icon  = "/icon/rust.svg"
  }
  option {
    name  = "Java"
    value = "java"
    icon  = "/icon/java.svg"
  }
  option {
    name  = "C/C++"
    value = "cpp"
    icon  = "/icon/cpp.svg"
  }
}

data "coder_parameter" "ides" {
  name         = "ides"
  display_name = "IDEs & Editors"
  description  = "Select the development environments for your workspace"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(["code-server"])
  mutable      = true
  icon         = "/icon/code.svg"
  order        = 2

  option {
    name  = "VS Code (Browser)"
    value = "code-server"
    icon  = "/icon/code.svg"
  }
  option {
    name  = "Cursor"
    value = "cursor"
    icon  = "/icon/cursor.svg"
  }
  option {
    name  = "JetBrains IDEs"
    value = "jetbrains"
    icon  = "/icon/jetbrains.svg"
  }
  option {
    name  = "Zed"
    value = "zed"
    icon  = "/icon/zed.svg"
  }
  option {
    name  = "Devin Desktop"
    value = "devin-desktop"
    icon  = "/icon/devin.svg"
  }
}

# Shown only when "JetBrains IDEs" is selected in the IDEs parameter.
# Pre-selects IDEs that match the chosen languages.
data "coder_parameter" "jetbrains_ides" {
  count        = contains(local.ides, "jetbrains") ? 1 : 0
  name         = "jetbrains_ides"
  display_name = "JetBrains IDEs"
  description  = "Select the JetBrains IDEs to install"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(local.jetbrains_ides_from_languages)
  mutable      = true
  icon         = "/icon/jetbrains.svg"
  order        = 3

  option {
    name  = "IntelliJ IDEA"
    value = "IU"
    icon  = "/icon/intellij.svg"
  }
  option {
    name  = "PyCharm"
    value = "PY"
    icon  = "/icon/pycharm.svg"
  }
  option {
    name  = "GoLand"
    value = "GO"
    icon  = "/icon/goland.svg"
  }
  option {
    name  = "WebStorm"
    value = "WS"
    icon  = "/icon/webstorm.svg"
  }
  option {
    name  = "RustRover"
    value = "RR"
    icon  = "/icon/rustrover.svg"
  }
  option {
    name  = "CLion"
    value = "CL"
    icon  = "/icon/clion.svg"
  }
  option {
    name  = "PhpStorm"
    value = "PS"
    icon  = "/icon/phpstorm.svg"
  }
  option {
    name  = "RubyMine"
    value = "RM"
    icon  = "/icon/rubymine.svg"
  }
  option {
    name  = "Rider"
    value = "RD"
    icon  = "/icon/rider.svg"
  }
}

data "coder_parameter" "git_repo" {
  name         = "git_repo"
  display_name = "Git Repository (Optional)"
  description  = "URL of a Git repository to clone into your workspace (leave empty to skip)"
  type         = "string"
  default      = ""
  mutable      = true
  icon         = "/icon/git.svg"
  order        = 4
}

# --- Locals ---

locals {
  username  = data.coder_workspace_owner.me.name
  languages = jsondecode(data.coder_parameter.languages.value)
  ides      = jsondecode(data.coder_parameter.ides.value)

  # Map selected languages to the relevant JetBrains IDE product codes.
  # Used as the default for the JetBrains IDE selector parameter.
  jetbrains_by_language = {
    python = ["PY"]
    go     = ["GO"]
    java   = ["IU"]
    nodejs = ["WS"]
    rust   = ["RR"]
    cpp    = ["CL"]
  }
  jetbrains_ides_from_languages = distinct(flatten([
    for lang in local.languages : lookup(local.jetbrains_by_language, lang, [])
  ]))

  # The actual JetBrains IDEs to install, from the user's selection
  # in the conditional JetBrains parameter (or empty if not shown).
  jetbrains_selected = contains(local.ides, "jetbrains") ? jsondecode(data.coder_parameter.jetbrains_ides[0].value) : []
}

# --- Agent ---

resource "coder_agent" "main" {
  arch           = data.coder_provisioner.me.arch
  os             = "linux"
  startup_script = <<-EOT
    set -e
    if [ ! -f ~/.init_done ]; then
      cp -rT /etc/skel ~
      touch ~/.init_done
    fi
  EOT

  env = {
    GIT_AUTHOR_NAME     = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
    GIT_AUTHOR_EMAIL    = "${data.coder_workspace_owner.me.email}"
    GIT_COMMITTER_NAME  = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
    GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
  }

  metadata {
    display_name = "CPU Usage"
    key          = "0_cpu_usage"
    script       = "coder stat cpu"
    interval     = 10
    timeout      = 1
  }

  metadata {
    display_name = "RAM Usage"
    key          = "1_ram_usage"
    script       = "coder stat mem"
    interval     = 10
    timeout      = 1
  }

  metadata {
    display_name = "Home Disk"
    key          = "3_home_disk"
    script       = "coder stat disk --path $${HOME}"
    interval     = 60
    timeout      = 1
  }
}

# --- Language installation ---
# All languages install in a single script to avoid apt-get lock
# conflicts (coder_script resources run in parallel).

resource "coder_script" "install_languages" {
  count              = length(local.languages) > 0 ? 1 : 0
  agent_id           = coder_agent.main.id
  display_name       = "Install Languages"
  icon               = "/icon/code.svg"
  run_on_start       = true
  start_blocks_login = true
  script = templatefile("${path.module}/install-languages.sh.tftpl", {
    LANGUAGES = join(",", local.languages)
  })
}

# --- Tool installation ---

resource "coder_script" "install_tools" {
  agent_id     = coder_agent.main.id
  display_name = "Install Tools"
  icon         = "/icon/terminal.svg"
  run_on_start = true
  script       = <<-EOT
    #!/usr/bin/env bash
    set -e

    # Install mise on first start. It lives in /home/coder, so later starts reuse it.
    if [ ! -x "$HOME/.local/bin/mise" ]; then
      curl -fsSL https://mise.run | sh
    fi
    export PATH="$HOME/.local/bin:$HOME/.local/share/mise/shims:$PATH"

    # Install the tools for everyone who uses the template, tracking the latest release.
    mise use -g ripgrep@latest bat@latest

    # Load mise in new interactive shells so the tools are on PATH.
    if ! grep -qs 'mise activate' "$HOME/.bashrc"; then
      echo 'eval "$(mise activate bash)"' >> "$HOME/.bashrc"
    fi
  EOT
}

# --- IDE modules ---

module "code-server" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "code-server") ? 1 : 0)
  source   = "registry.coder.com/coder/code-server/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  order    = 1
}

module "cursor" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "cursor") ? 1 : 0)
  source   = "registry.coder.com/coder/cursor/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 3
}

# TODO: Re-add the coder/jetbrains module once Coder's dynamic
# parameter system respects module count for parameter visibility.
# The module's internal coder_parameter appears even when count = 0,
# creating a ghost parameter in the workspace creation form.
# module "jetbrains" {
#   count    = data.coder_workspace.me.start_count * (contains(local.ides, "jetbrains") && length(local.jetbrains_selected) > 0 ? 1 : 0)
#   source   = "registry.coder.com/coder/jetbrains/coder"
#   version  = "~> 1.0"
#   agent_id = coder_agent.main.id
#   folder   = "/home/coder"
#   default  = toset(local.jetbrains_selected)
# }

module "zed" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "zed") ? 1 : 0)
  source   = "registry.coder.com/coder/zed/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 5
}

module "devin-desktop" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "devin-desktop") ? 1 : 0)
  source   = "registry.coder.com/coder/devin-desktop/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 6
}

# --- Git clone ---

module "git-clone" {
  count    = data.coder_workspace.me.start_count * (data.coder_parameter.git_repo.value != "" ? 1 : 0)
  source   = "registry.coder.com/coder/git-clone/coder"
  version  = "~> 2.0"
  agent_id = coder_agent.main.id
  url      = data.coder_parameter.git_repo.value
}

# --- Presets ---

data "coder_workspace_preset" "web_dev" {
  name = "Web Development"
  icon = "/icon/nodejs.svg"
  parameters = {
    languages = jsonencode(["python", "nodejs"])
    ides      = jsonencode(["code-server"])
    git_repo  = ""
  }
}

data "coder_workspace_preset" "backend_go" {
  name = "Backend (Go)"
  icon = "/icon/go.svg"
  parameters = {
    languages      = jsonencode(["go"])
    ides           = jsonencode(["code-server", "jetbrains"])
    jetbrains_ides = jsonencode(["GO"])
    git_repo       = ""
  }
}

data "coder_workspace_preset" "data_science" {
  name = "Data Science"
  icon = "/icon/python.svg"
  parameters = {
    languages = jsonencode(["python"])
    ides      = jsonencode(["code-server"])
    git_repo  = ""
  }
}

data "coder_workspace_preset" "full_stack" {
  name = "Full Stack"
  icon = "/icon/code.svg"
  parameters = {
    languages = jsonencode(["python", "nodejs", "go"])
    ides      = jsonencode(["code-server", "cursor"])
    git_repo  = ""
  }
}

# --- Docker resources ---

resource "docker_volume" "home_volume" {
  name = "coder-${data.coder_workspace.me.id}-home"
  lifecycle {
    ignore_changes = all
  }
  labels {
    label = "coder.owner"
    value = data.coder_workspace_owner.me.name
  }
  labels {
    label = "coder.owner_id"
    value = data.coder_workspace_owner.me.id
  }
  labels {
    label = "coder.workspace_id"
    value = data.coder_workspace.me.id
  }
  labels {
    label = "coder.workspace_name_at_creation"
    value = data.coder_workspace.me.name
  }
  depends_on = []
}

resource "docker_volume" "homebrew_volume" {
  name = "coder-${data.coder_workspace.me.id}-homebrew"
  lifecycle {
    ignore_changes = all
  }
}

resource "docker_container" "workspace" {
  count    = data.coder_workspace.me.start_count
  image    = "codercom/example-base:ubuntu"
  name     = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
  hostname = data.coder_workspace.me.name
  entrypoint = [
    "sh", "-c",
    replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal"),
  ]
  env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
  host {
    host = "host.docker.internal"
    ip   = "host-gateway"
  }
  volumes {
    container_path = "/home/coder"
    volume_name    = docker_volume.home_volume.name
    read_only      = false
  }
  volumes {
    container_path = "/home/linuxbrew"
    volume_name    = docker_volume.homebrew_volume.name
    read_only      = false
  }
  labels {
    label = "coder.owner"
    value = data.coder_workspace_owner.me.name
  }
  labels {
    label = "coder.owner_id"
    value = data.coder_workspace_owner.me.id
  }
  labels {
    label = "coder.workspace_id"
    value = data.coder_workspace.me.id
  }
  labels {
    label = "coder.workspace_name"
    value = data.coder_workspace.me.name
  }
  depends_on = []
}
```

</details>

## What's next?

Now that you can install your own tools, [clone private repositories](./authenticate-to-github.md) so your workspaces can reach your private GitHub code.

## Learn more

- [Homebrew documentation](https://brew.sh/) for the package manager
- [mise documentation](https://mise.jdx.dev/) for the version manager
- [Resource persistence](../../admin/templates/extending-templates/resource-persistence.md) in the Coder documentation
- [Dotfiles](../../user-guides/workspace-dotfiles.md) in the Coder documentation

---

# Clone private repositories

Source: https://coder.com/docs/get-started/customize-your-template/authenticate-to-github

Now that you've finished [Launch your first workspace](../index.md), you can let your workspaces clone private GitHub repositories without a manual login each time.

The Quickstart template already clones **public** repositories through its **Git Repository (Optional)** parameter with no extra setup.
A **private** repository needs authentication, which is what you add here.
In this guide, you add the `coder_external_auth` data source, connect your workspace to GitHub, and clone a private repository with no manual login.
This guide uses GitHub, and the same external-auth pattern works for other providers.

> [!NOTE]
> This guide assumes your Quickstart template is open for editing.
> If it's not, you can edit the template from the web by finding the template, selecting the three dots menu, and selecting **Edit files**.
> Refer to [Customize workspace startup](./index.md#open-the-template-for-editing) for more information.

## What you'll do

- ✅ Add the `coder_external_auth` data source to the template.
- ✅ Connect your workspace to GitHub with the **Login with GitHub** button.
- ✅ Clone a private repository without a manual login.

## Data sources for their side effect

You already met one [data source](https://developer.hashicorp.com/terraform/language/data-sources) in [Add a programming language](./add-a-language.md): `coder_parameter` reads a choice from the workspace owner.

`coder_external_auth` is a data source you add for its side effect rather than its value.
Its presence tells Coder that a workspace requires an authenticated session with a provider before it starts.
The `id` points at a provider configured on the Coder deployment, and the local control plane you started in Part 1 already has a `github` provider available.

> [!NOTE]
> External authentication lets a workspace sign in to an outside service, such as a Git provider, before it starts.
> A default Coder install includes a built-in GitHub app, so `id = "github"` works without extra setup.
> An admin can configure other providers (GitLab, Bitbucket, Azure DevOps, or generic OIDC) or replace the built-in GitHub app.
> To learn more, refer to [External authentication](../../admin/external-auth/index.md).

## Step 1: Require GitHub authentication

Add this `coder_external_auth` block to `main.tf`:

```tf
data "coder_external_auth" "github" {
  id = "github"
}
```

Then publish a new version of the template:

<div class="tabs">

### UI

In the web editor, add the `coder_external_auth` block to `main.tf`.
Select **Build**, wait for the build to pass, then select **Publish**.

### CLI

Add the block to `~/coder-quickstart/main.tf`, then publish a new version:

```sh
coder templates push -d ~/coder-quickstart -y quickstart
```

</div>

> [!WARNING]
> Adding this block makes GitHub authentication required: a workspace on this template can't start until you authenticate, with no option to skip.
> If you'd rather leave it optional, set `optional = true` in the `coder_external_auth` block so users can skip authentication when they create or update a workspace.

## Step 2: Connect your workspace to GitHub

Update the workspace you built in [Launch your first workspace](../index.md) to the version you just published.
Because the local control plane is already connected to GitHub, you don't configure an OAuth app; you only authorize the workspace.

<div class="tabs">

### UI

On your workspace, select **Update**.
The update form shows a **Login with GitHub** button: select it, follow the prompts to authorize Coder, then select **Update and restart**.
The following screenshot shows the **External Authentication** section of the workspace creation screen before connecting GitHub:

![External Authentication with GitHub before logging in](../../images/screenshots/login-with-github-logged-out.png)_External Authentication with GitHub before logging in_

### CLI

Update the workspace:

```sh
coder update <your-workspace>
```

If you aren't authenticated yet, Coder prints a URL to log in with GitHub; open it, authorize Coder, then run the command again.

</div>

Once you authorize Coder, the workspace starts, and Coder stores and refreshes your GitHub token for later builds.
After authorizing Coder, Coder replaces the **Login with GitHub** button with an **Authenticated** message:

![External Authentication with GitHub after logging in](../../images/screenshots/login-with-github-logged-in.png)_External Authentication with GitHub after logging in_

## Step 3: Clone a private repository

Now that your workspace is connected to GitHub, point the **Git Repository (Optional)** parameter at a private repository.

<div class="tabs">

### UI

On your workspace, set **Git Repository (Optional)** to your private repository URL in the update form, then select **Update and restart**.

### CLI

Update the workspace and re-select its parameters:

```sh
coder update <your-workspace> --always-prompt
```

When prompted for **Git Repository (Optional)**, enter your private repository URL, then let the workspace rebuild.

</div>

On the next build, the workspace clones the private repository with no manual login, because Coder supplies your GitHub token to `git`.

## What just happened

You added one data source and connected your workspace to GitHub:

- `coder_external_auth` declared that the workspace needs an authenticated GitHub session before it starts.
- Selecting **Login with GitHub** authorized Coder, and Coder now supplies a GitHub token to `git` for every build.

A `coder_parameter` reads an answer from the workspace owner.
A `coder_external_auth` data source reaches outside the template for a prerequisite the deployment provides.
Both are data sources, and neither creates infrastructure.

## Final code

<details>

<summary>The complete <code>main.tf</code></summary>

Your `main.tf` after this guide's changes, starting from the Quickstart template:

```tf
terraform {
  required_providers {
    coder = {
      source = "coder/coder"
    }
    docker = {
      source = "kreuzwerker/docker"
    }
    external = {
      source = "hashicorp/external"
    }
  }
}

variable "docker_socket" {
  default     = ""
  description = "(Optional) Docker socket URI"
  type        = string
}

provider "docker" {
  host = var.docker_socket != "" ? var.docker_socket : null
}

data "coder_provisioner" "me" {}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}

# --- Parameters ---

data "coder_parameter" "languages" {
  name         = "languages"
  display_name = "Programming Languages"
  description  = "Select the languages to pre-install in your workspace"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(["python"])
  mutable      = true
  icon         = "/icon/code.svg"
  order        = 1

  option {
    name  = "Python"
    value = "python"
    icon  = "/icon/python.svg"
  }
  option {
    name  = "Node.js"
    value = "nodejs"
    icon  = "/icon/nodejs.svg"
  }
  option {
    name  = "Go"
    value = "go"
    icon  = "/icon/go.svg"
  }
  option {
    name  = "Rust"
    value = "rust"
    icon  = "/icon/rust.svg"
  }
  option {
    name  = "Java"
    value = "java"
    icon  = "/icon/java.svg"
  }
  option {
    name  = "C/C++"
    value = "cpp"
    icon  = "/icon/cpp.svg"
  }
}

data "coder_parameter" "ides" {
  name         = "ides"
  display_name = "IDEs & Editors"
  description  = "Select the development environments for your workspace"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(["code-server"])
  mutable      = true
  icon         = "/icon/code.svg"
  order        = 2

  option {
    name  = "VS Code (Browser)"
    value = "code-server"
    icon  = "/icon/code.svg"
  }
  option {
    name  = "Cursor"
    value = "cursor"
    icon  = "/icon/cursor.svg"
  }
  option {
    name  = "JetBrains IDEs"
    value = "jetbrains"
    icon  = "/icon/jetbrains.svg"
  }
  option {
    name  = "Zed"
    value = "zed"
    icon  = "/icon/zed.svg"
  }
  option {
    name  = "Devin Desktop"
    value = "devin-desktop"
    icon  = "/icon/devin.svg"
  }
}

# Shown only when "JetBrains IDEs" is selected in the IDEs parameter.
# Pre-selects IDEs that match the chosen languages.
data "coder_parameter" "jetbrains_ides" {
  count        = contains(local.ides, "jetbrains") ? 1 : 0
  name         = "jetbrains_ides"
  display_name = "JetBrains IDEs"
  description  = "Select the JetBrains IDEs to install"
  type         = "list(string)"
  form_type    = "multi-select"
  default      = jsonencode(local.jetbrains_ides_from_languages)
  mutable      = true
  icon         = "/icon/jetbrains.svg"
  order        = 3

  option {
    name  = "IntelliJ IDEA"
    value = "IU"
    icon  = "/icon/intellij.svg"
  }
  option {
    name  = "PyCharm"
    value = "PY"
    icon  = "/icon/pycharm.svg"
  }
  option {
    name  = "GoLand"
    value = "GO"
    icon  = "/icon/goland.svg"
  }
  option {
    name  = "WebStorm"
    value = "WS"
    icon  = "/icon/webstorm.svg"
  }
  option {
    name  = "RustRover"
    value = "RR"
    icon  = "/icon/rustrover.svg"
  }
  option {
    name  = "CLion"
    value = "CL"
    icon  = "/icon/clion.svg"
  }
  option {
    name  = "PhpStorm"
    value = "PS"
    icon  = "/icon/phpstorm.svg"
  }
  option {
    name  = "RubyMine"
    value = "RM"
    icon  = "/icon/rubymine.svg"
  }
  option {
    name  = "Rider"
    value = "RD"
    icon  = "/icon/rider.svg"
  }
}

data "coder_parameter" "git_repo" {
  name         = "git_repo"
  display_name = "Git Repository (Optional)"
  description  = "URL of a Git repository to clone into your workspace (leave empty to skip)"
  type         = "string"
  default      = ""
  mutable      = true
  icon         = "/icon/git.svg"
  order        = 4
}

# --- External authentication ---

data "coder_external_auth" "github" {
  id = "github"
}

# --- Locals ---

locals {
  username  = data.coder_workspace_owner.me.name
  languages = jsondecode(data.coder_parameter.languages.value)
  ides      = jsondecode(data.coder_parameter.ides.value)

  # Map selected languages to the relevant JetBrains IDE product codes.
  # Used as the default for the JetBrains IDE selector parameter.
  jetbrains_by_language = {
    python = ["PY"]
    go     = ["GO"]
    java   = ["IU"]
    nodejs = ["WS"]
    rust   = ["RR"]
    cpp    = ["CL"]
  }
  jetbrains_ides_from_languages = distinct(flatten([
    for lang in local.languages : lookup(local.jetbrains_by_language, lang, [])
  ]))

  # The actual JetBrains IDEs to install, from the user's selection
  # in the conditional JetBrains parameter (or empty if not shown).
  jetbrains_selected = contains(local.ides, "jetbrains") ? jsondecode(data.coder_parameter.jetbrains_ides[0].value) : []
}

# --- Agent ---

resource "coder_agent" "main" {
  arch           = data.coder_provisioner.me.arch
  os             = "linux"
  startup_script = <<-EOT
    set -e
    if [ ! -f ~/.init_done ]; then
      cp -rT /etc/skel ~
      touch ~/.init_done
    fi
  EOT

  env = {
    GIT_AUTHOR_NAME     = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
    GIT_AUTHOR_EMAIL    = "${data.coder_workspace_owner.me.email}"
    GIT_COMMITTER_NAME  = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
    GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
  }

  metadata {
    display_name = "CPU Usage"
    key          = "0_cpu_usage"
    script       = "coder stat cpu"
    interval     = 10
    timeout      = 1
  }

  metadata {
    display_name = "RAM Usage"
    key          = "1_ram_usage"
    script       = "coder stat mem"
    interval     = 10
    timeout      = 1
  }

  metadata {
    display_name = "Home Disk"
    key          = "3_home_disk"
    script       = "coder stat disk --path $${HOME}"
    interval     = 60
    timeout      = 1
  }
}

# --- Language installation ---
# All languages install in a single script to avoid apt-get lock
# conflicts (coder_script resources run in parallel).

resource "coder_script" "install_languages" {
  count              = length(local.languages) > 0 ? 1 : 0
  agent_id           = coder_agent.main.id
  display_name       = "Install Languages"
  icon               = "/icon/code.svg"
  run_on_start       = true
  start_blocks_login = true
  script = templatefile("${path.module}/install-languages.sh.tftpl", {
    LANGUAGES = join(",", local.languages)
  })
}

# --- IDE modules ---

module "code-server" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "code-server") ? 1 : 0)
  source   = "registry.coder.com/coder/code-server/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  order    = 1
}

module "cursor" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "cursor") ? 1 : 0)
  source   = "registry.coder.com/coder/cursor/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 3
}

# TODO: Re-add the coder/jetbrains module once Coder's dynamic
# parameter system respects module count for parameter visibility.
# The module's internal coder_parameter appears even when count = 0,
# creating a ghost parameter in the workspace creation form.
# module "jetbrains" {
#   count    = data.coder_workspace.me.start_count * (contains(local.ides, "jetbrains") && length(local.jetbrains_selected) > 0 ? 1 : 0)
#   source   = "registry.coder.com/coder/jetbrains/coder"
#   version  = "~> 1.0"
#   agent_id = coder_agent.main.id
#   folder   = "/home/coder"
#   default  = toset(local.jetbrains_selected)
# }

module "zed" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "zed") ? 1 : 0)
  source   = "registry.coder.com/coder/zed/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 5
}

module "devin-desktop" {
  count    = data.coder_workspace.me.start_count * (contains(local.ides, "devin-desktop") ? 1 : 0)
  source   = "registry.coder.com/coder/devin-desktop/coder"
  version  = "~> 1.0"
  agent_id = coder_agent.main.id
  folder   = "/home/coder"
  order    = 6
}

# --- Git clone ---

module "git-clone" {
  count    = data.coder_workspace.me.start_count * (data.coder_parameter.git_repo.value != "" ? 1 : 0)
  source   = "registry.coder.com/coder/git-clone/coder"
  version  = "~> 2.0"
  agent_id = coder_agent.main.id
  url      = data.coder_parameter.git_repo.value
}

# --- Presets ---

data "coder_workspace_preset" "web_dev" {
  name = "Web Development"
  icon = "/icon/nodejs.svg"
  parameters = {
    languages = jsonencode(["python", "nodejs"])
    ides      = jsonencode(["code-server"])
    git_repo  = ""
  }
}

data "coder_workspace_preset" "backend_go" {
  name = "Backend (Go)"
  icon = "/icon/go.svg"
  parameters = {
    languages      = jsonencode(["go"])
    ides           = jsonencode(["code-server", "jetbrains"])
    jetbrains_ides = jsonencode(["GO"])
    git_repo       = ""
  }
}

data "coder_workspace_preset" "data_science" {
  name = "Data Science"
  icon = "/icon/python.svg"
  parameters = {
    languages = jsonencode(["python"])
    ides      = jsonencode(["code-server"])
    git_repo  = ""
  }
}

data "coder_workspace_preset" "full_stack" {
  name = "Full Stack"
  icon = "/icon/code.svg"
  parameters = {
    languages = jsonencode(["python", "nodejs", "go"])
    ides      = jsonencode(["code-server", "cursor"])
    git_repo  = ""
  }
}

# --- Docker resources ---

resource "docker_volume" "home_volume" {
  name = "coder-${data.coder_workspace.me.id}-home"
  lifecycle {
    ignore_changes = all
  }
  labels {
    label = "coder.owner"
    value = data.coder_workspace_owner.me.name
  }
  labels {
    label = "coder.owner_id"
    value = data.coder_workspace_owner.me.id
  }
  labels {
    label = "coder.workspace_id"
    value = data.coder_workspace.me.id
  }
  labels {
    label = "coder.workspace_name_at_creation"
    value = data.coder_workspace.me.name
  }
  depends_on = []
}

resource "docker_container" "workspace" {
  count    = data.coder_workspace.me.start_count
  image    = "codercom/example-base:ubuntu"
  name     = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
  hostname = data.coder_workspace.me.name
  entrypoint = [
    "sh", "-c",
    replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal"),
  ]
  env = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
  host {
    host = "host.docker.internal"
    ip   = "host-gateway"
  }
  volumes {
    container_path = "/home/coder"
    volume_name    = docker_volume.home_volume.name
    read_only      = false
  }
  labels {
    label = "coder.owner"
    value = data.coder_workspace_owner.me.name
  }
  labels {
    label = "coder.owner_id"
    value = data.coder_workspace_owner.me.id
  }
  labels {
    label = "coder.workspace_id"
    value = data.coder_workspace.me.id
  }
  labels {
    label = "coder.workspace_name"
    value = data.coder_workspace.me.name
  }
  depends_on = []
}
```

</details>

## What's next?

You finished the Customize your template series, and your workspaces can now clone private repositories.

This is the last guide in the series. To keep going, explore more of what Coder offers:

- [Manage workspaces for your team](../../user-guides/workspace-management.md).
- [Try Coder Agents](../../ai-coder/agents/getting-started.md), the chat interface and API for delegating work to coding agents.

Or revisit the [Customize your template overview](./index.md) for the full list of guides.

## Learn more

- [External authentication](../../admin/external-auth/index.md) in the Coder documentation
- [coder_external_auth data source](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/external_auth) in the Terraform Registry
- [Terraform data sources](https://developer.hashicorp.com/terraform/language/data-sources)

---

# Install Coder in your infrastructure

Source: https://coder.com/docs/install

This section describes how to plan, install, and configure a Coder deployment, from the initial decisions you need to make in order to successfully run Coder to a steady-state operating environment.
The five phases are meant to be read in order: each phase produces the required information for the next phase.

> [!TIP]
> If you only need the `coder` command-line client on your own machine, refer to [Coder CLI](./cli.md).
> You don't need the rest of this section.
>
> If you want a Coder deployment on a single machine as quickly as possible, follow the [Quickstart](../get-started/index.md) instead.
> It installs Coder and launches a first workspace without the planning and preparation work described here.
> Come back to this section when you want an expanded Coder deployment.

## The five phases

| Phase                                              | What it answers                                                          | What you finish with                                                           |
|----------------------------------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------------------------|
| [1. Plan your deployment](./plan/index.md)         | Which components run where, how large they need to be, who operates them | A deployment shape and a size target you can hand to an infrastructure team    |
| [2. Prepare prerequisites](./prepare/index.md)     | What must exist before installation starts, and who owns each piece      | DNS, certificates, a database, a license, and an identity provider application |
| [3. Install the control plane](./server/index.md)  | How to install Coder on the platform your team operates                  | A running Coder deployment you can sign in to                                  |
| [4. Validate your deployment](./validate/index.md) | Whether the deployment is hardened, works, and holds up under load       | Evidence that the deployment is ready for real users                           |
| [5. Operate and maintain](./operate/index.md)      | How to keep the deployment healthy, upgraded, and correctly sized        | An upgrade and scaling routine, plus a removal path                            |

Phases 1 and 2 are advisory rather than a gate.
Nothing stops you from installing the control plane first, but the recommendations in those phases are what keep a deployment from needing to be rebuilt later.
Don't know where to start?
Read [Plan your deployment](./plan/index.md) and [Prepare prerequisites](./prepare/index.md) first.

<children></children>

## Who does the work

A Coder deployment usually crosses team boundaries.
The following actors appear throughout this section, so you can anticipate which conversations you need to start and how long they're likely to take.

| Actor                            | Responsible for                                                              | Appears in phase |
|----------------------------------|------------------------------------------------------------------------------|------------------|
| Coder platform owner             | The deployment itself: installation, configuration, upgrades, and support    | 1 to 5           |
| Infrastructure team              | Clusters, virtual machines, networking, load balancers, and egress rules     | 1 to 4           |
| DNS and TLS owner                | The Coder hostname, the wildcard record for workspace apps, and certificates | 2                |
| Database administrator           | PostgreSQL provisioning, sizing, backups, and restore tests                  | 2, 4, 5          |
| Identity provider administrator  | The OIDC or SAML application, claims, and group mappings                     | 2                |
| Security and compliance reviewer | Audit requirements, network policy, data handling, and sign-off              | 2, 4             |
| Licensing contact                | Purchasing and renewing the Coder license                                    | 2                |
| Template author                  | The workspace templates developers use once the deployment is running        | 4, 5             |

These are roles, not people.
One person may serve as several actors, which is common for a proof of concept run by a single platform engineer.
Several people may also serve as one actor, which is common for an infrastructure team that splits networking and compute ownership.
Use the table to identify who has to agree, not to count headcount.

---

# Install the Coder CLI

Source: https://coder.com/docs/install/cli

A single CLI (`coder`) is used for both the control plane and the client.

We support two release channels: mainline and stable - read the
[Releases](../reference/releases.md) page to learn more about which best suits your team.

## Download the latest release from GitHub

<div class="tabs">

## Linux/macOS

Our install script is the fastest way to install Coder on Linux/macOS:

```sh
curl -fsSL https://coder.com/install.sh | sh
```

Refer to [GitHub releases](https://github.com/coder/coder/releases) for
alternate installation methods (e.g. standalone binaries, system packages).

To run the Coder control plane on a Red Hat Enterprise Linux host or another RHEL-family distribution, refer to [Install Coder on RHEL-family Linux](./server/rpm.md).

## Windows

If you plan to use the built-in PostgreSQL database, ensure that the
[Visual C++ Runtime](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist#latest-microsoft-visual-c-redistributable-version)
is installed.

Use [GitHub releases](https://github.com/coder/coder/releases) to download the
Windows installer (`.msi`) or standalone binary (`.exe`).

![Windows setup wizard](../images/install/windows-installer.png)

Alternatively, you can use the
[`winget`](https://learn.microsoft.com/en-us/windows/package-manager/winget/#use-winget)
package manager to install Coder:

```ps1
winget install Coder.Coder
```

</div>

To start the control plane:

```sh
coder server
```

![Coder install](../images/screenshots/welcome-create-admin-user.png)

To log in to an existing Coder deployment:

```sh
coder login https://coder.example.com
```

## Download the CLI from your deployment

> [!NOTE]
> Available in Coder 2.19 and newer on macOS and Linux clients only.

Every control plane hosts CLI binaries for all supported platforms. You can run a
script to download the appropriate CLI for your machine from your Coder
deployment.

![Install Coder binary from your deployment](../images/install/install_from_deployment.png)

This script works within air-gapped deployments and ensures that the version of
the CLI you have installed on your machine matches the version of the control plane.

This script can be useful when authoring a template for installing the CLI.

### Next up

- [Create your first template](../tutorials/template-from-scratch.md)
- [Control plane configuration](../admin/setup/index.md)

---

# 1. Plan your deployment

Source: https://coder.com/docs/install/plan

Planning decides the shape of your deployment: which components run where, how large they need to be, and which choices are expensive to change later.
Work through this phase before you pick a platform in [Install the control plane](../server/index.md).

## What you decide here

- **Topology**: where the control plane, the database, and workspaces run, and whether workspaces run in the same region as their users.
  Refer to [Architecture](./architecture.md).
- **Size**: how much CPU, memory, and database capacity the deployment needs for the number of users you expect.
  Refer to [Coder Validated Architecture](./sizing/index.md).
- **Provisioning model**: whether workspace builds run on the control plane or on [external provisioners](../operate/provisioners/index.md), which matters when builds need credentials the control plane shouldn't hold.
- **Network position**: whether the deployment is reachable from the public internet, from a private network only, or is [air-gapped](../prepare/airgap.md).

## Who to involve

The Coder platform owner drives this phase, but the topology and size decisions need the infrastructure team, and a network position decision usually needs a security reviewer.
Bring them in now: these are the decisions that are hardest to revisit after installation.

## Before you move on

You should be able to state, in a sentence each, where Coder will run, how many users it's sized for, and how users will reach it.
If any of those are unclear, the answer usually lives in [Architecture](./architecture.md) or in the [Coder Validated Architecture](./sizing/index.md) reference designs.

Next: [Prepare prerequisites](../prepare/index.md).

<children></children>

---

# Architecture

Source: https://coder.com/docs/install/plan/architecture

The Coder deployment model is flexible and offers various components that
platform administrators can deploy and scale depending on their use case. This
page describes possible deployments, challenges, and risks associated with them.

<div class="tabs">

## Community and Premium editions

![Single Region Architecture Diagram](../../images/single-region-architecture.png)

## Multi-Region Premium edition

![Multi Region Architecture Diagram](../../images/architecture-multi-region.png)

</div>

## Primary components

### coderd

`coderd` is the process that runs the control plane, started with
`coder server`. It is a thin API that connects workspaces, provisioners and
users. `coderd` stores its state in Postgres and is the only component that
communicates with Postgres.

It offers:

- Dashboard (UI)
- HTTP API
- Dev URLs (HTTP reverse proxy to workspaces)
- Workspace Web Applications (e.g for easy access to `code-server`)
- Agent registration

### provisionerd

_provisionerd_ is the execution context for infrastructure modifying providers.
At the moment, the only provider is Terraform (running `terraform`).

By default, the control plane runs multiple provisioner daemons.
[External provisioners](../operate/provisioners/index.md) can be added for security or
scalability purposes.

### Workspaces

At the highest level, a workspace is a set of cloud resources. These resources
can be VMs, Kubernetes clusters, storage buckets, or whatever else Terraform
lets you dream up.

The resources that run the workspace agent are described as _computational
resources_, while those that don't are called _peripheral resources_.

Each resource may also be _persistent_ or _ephemeral_ depending on whether
they're destroyed on workspace stop.

### Agents

A workspace agent is the Coder process that runs within a user's remote
workspace. It provides a consistent interface for `coderd` and clients to
communicate with workspaces regardless of operating system, architecture, or
cloud.

It offers the following services along with much more:

- SSH
- Port forwarding
- Liveness checks
- `startup_script` automation

Templates are responsible for
[creating and running agents](../../admin/templates/extending-templates/index.md#workspace-agents)
within workspaces.

## Service Bundling

While `coderd` and Postgres can be orchestrated independently, our default
installation paths bundle them all together into one system service. It's
perfectly fine to run a production deployment this way, but there are certain
situations that necessitate decomposition:

- Reducing global client latency (distribute `coderd` and centralize database)
- Achieving greater availability and efficiency (horizontally scale individual
  services)

## Data Layer

### PostgreSQL (Recommended)

While `coderd` runs a bundled version of PostgreSQL, we recommend running an
external PostgreSQL 13+ database for production deployments.

A managed PostgreSQL database, with daily backups, is recommended:

- For AWS: Amazon RDS for PostgreSQL (preferably using
  [RDS IAM authentication](../../reference/cli/server/index.md#--postgres-auth)).
- For Azure: Azure Database for PostgreSQL
- Flexible Server For GCP: Cloud SQL for PostgreSQL

Learn more about database requirements:
[Database Health](../../admin/monitoring/health-check.md#database)

### Git Providers (Recommended)

Users will likely need to pull source code and other artifacts from a git
provider. The Coder control plane and workspaces will need network connectivity
to the git provider.

- [GitHub Enterprise](../../admin/external-auth/index.md#github-enterprise)
- [GitLab](../../admin/external-auth/index.md#gitlab-self-managed)
- [BitBucket](../../admin/external-auth/index.md#bitbucket-server)
- [Other Providers](../../admin/external-auth/index.md#self-managed-git-providers)

### Artifact Manager (Optional)

Workspaces and templates can pull artifacts from an artifact manager, such as
JFrog Artifactory. This can be configured on the infrastructure level, or in
some cases within Coder:

- Tutorial: [JFrog Artifactory and Coder](../../admin/integrations/jfrog-artifactory.md)

### Container Registry (Optional)

If you prefer not to pull container images for the control plane (`coderd`,
`provisionerd`) and workspaces from public container registry (Docker Hub,
GitHub Container Registry) you can run your own container registry with Coder.

To shorten the provisioning time, it is recommended to deploy registry mirrors
in the same region as the workspace nodes.

## Governance Layer

The governance layer provides centralized oversight and policy enforcement for
AI-powered development within Coder workspaces.

### AI Gateway

AI Gateway is a centralized feature that sits between coding agents and LLM providers such as OpenAI and Anthropic.
Users authenticate through Coder instead of managing separate provider API keys.
All prompts, token usage, and tool invocations are recorded for compliance and cost tracking.

AI Gateway supports 2 deployment topologies:

- **Embedded:** `coderd` runs the AI Gateway data plane in the same process.
- **Standalone:** gateway replicas run outside `coderd`, serve AI traffic, and send requests directly to upstream providers.

Standalone replicas have no authoritative database state.
They keep ephemeral provider snapshots, caches, and metrics in memory, and can optionally write API dumps to local disk.
`coderd` is the source of truth and the only component that writes AI Gateway state to the database.
Each replica maintains a control connection to `coderd` for Coder API key validation, provider configuration, and AI session recording, and becomes unready when that connection is unavailable.

Refer to [AI Gateway](../../ai-coder/ai-gateway/index.md) and [standalone deployment](../../ai-coder/ai-gateway/standalone.md) for configuration and operational guidance.

### Agent Firewall

Agent Firewall is a process-level firewall that restricts and audits network
access for AI agents running in workspaces. It enforces allowlist-based policies
controlling which domains, HTTP methods, and URL paths agents can reach, while
streaming audit logs to the Coder control plane for centralized monitoring.

Learn more: [Agent Firewall](../../ai-coder/agent-firewall/index.md)

---

# Coder Validated Architecture

Source: https://coder.com/docs/install/plan/sizing

Many customers operate Coder in complex organizational environments, consisting
of multiple business units, agencies, and/or subsidiaries. This can lead to
numerous Coder deployments, due to discrepancies in regulatory compliance, data
sovereignty, and level of funding across groups. The Coder Validated
Architecture (CVA) prescribes a Kubernetes-based deployment approach, enabling
your organization to deploy a stable Coder instance that is easier to maintain
and troubleshoot.

The following sections will detail the components of the Coder Validated
Architecture, provide guidance on how to configure and deploy these components,
and offer insights into how to maintain and troubleshoot your Coder environment.

- [General concepts](#general-concepts)
- [Kubernetes Infrastructure](#kubernetes-infrastructure)
- [PostgreSQL Database](#postgresql-database)
- [Operational readiness](#operational-readiness)

## Who is this document for?

This guide targets the following personas. It assumes a basic understanding of
cloud/on-premise computing, containerization, and the Coder platform.

| Role                      | Description                                                                    |
|---------------------------|--------------------------------------------------------------------------------|
| Platform Engineers        | Responsible for deploying, operating the Coder deployment and infrastructure   |
| Enterprise Architects     | Responsible for architecting Coder deployments to meet enterprise requirements |
| Managed Service Providers | Entities that deploy and run Coder software as a service for customers         |

## CVA Guidance

| CVA provides:                                  | CVA does not provide:                                                                    |
|------------------------------------------------|------------------------------------------------------------------------------------------|
| Single and multi-region K8s deployment options | Prescribing OS, or cloud vs. on-premise                                                  |
| Reference architectures for up to 3,000 users  | An approval of your architecture; the CVA solely provides recommendations and guidelines |
| Best practices for building a Coder deployment | Recommendations for every possible deployment scenario                                   |

For higher level design principles and architectural best practices, see Coder's
[Well-Architected Framework](https://coder.com/blog/coder-well-architected-framework).

## General concepts

This section outlines core concepts and terminology essential for understanding
Coder's architecture and deployment strategies.

### Administrator

An administrator is a user role within the Coder platform with elevated
privileges. Admins have access to administrative functions such as user
management, template definitions, insights, and deployment configuration.

### Coder control plane

Coder's control plane, run by the `coderd` process, is the main component
recommended for deployment with multiple replicas to ensure high availability.
It provides an API for managing workspaces and templates, and serves the
dashboard UI. In addition, each `coderd` replica hosts 3 Terraform
[provisioners](#provisioner) by default.

### User

A [user](../../../admin/users/index.md) is an individual who utilizes the Coder platform
to develop, test, and deploy applications using workspaces. Users can select
available templates to provision workspaces. They interact with Coder using the
web interface, the CLI tool, or directly calling API methods.

### Workspace

A [workspace](../../../user-guides/workspace-management.md) refers to an
isolated development environment where users can write, build, and run code.
Workspaces are fully configurable and can be tailored to specific project
requirements, providing developers with a consistent and efficient development
environment. Workspaces can be autostarted and autostopped, enabling efficient
resource management.

Users can connect to workspaces using SSH or via workspace applications like
`code-server`, facilitating collaboration and remote access. Additionally,
workspaces can be parameterized, allowing users to customize settings and
configurations based on their unique needs. Workspaces are instantiated using
Coder templates and deployed on resources created by provisioners.

### Template

A [template](../../../admin/templates/index.md) in Coder is a predefined
configuration for creating workspaces. Templates streamline the process of
workspace creation by providing pre-configured settings, tooling, and
dependencies. They are built by template administrators on top of Terraform,
allowing for efficient management of infrastructure resources. Additionally,
templates can utilize Coder modules to leverage existing features shared with
other templates, enhancing flexibility and consistency across deployments.
Templates describe provisioning rules for infrastructure resources offered by
Terraform providers.

### Workspace Proxy

A [workspace proxy](../../../admin/networking/workspace-proxies.md) serves as a
relay connection option for developers connecting to their workspace over SSH, a
workspace app, or through port forwarding. It helps reduce network latency for
geo-distributed teams by minimizing the distance network traffic needs to
travel. Notably, workspace proxies do not handle dashboard connections or API
calls.

### Provisioner

Provisioners in Coder execute Terraform during workspace and template builds.
While the platform includes built-in provisioner daemons by default, there are
advantages to employing external provisioners. These external daemons provide
secure build environments and reduce server load, improving performance and
scalability. Each provisioner can handle a single concurrent workspace build,
allowing for efficient resource allocation and workload management.

### Registry

The [Coder Registry](https://registry.coder.com) is a platform where you can
find starter templates and _Modules_ for various cloud services and platforms.

Templates help create self-service development environments using
Terraform-defined infrastructure, while _Modules_ simplify template creation by
providing common features like workspace applications, third-party integrations,
or helper scripts.

Please note that the Registry is a hosted service and isn't available for
offline use.

### AI Gateway

[AI Gateway](../../../ai-coder/ai-gateway/index.md) proxies AI provider traffic and records each AI session.
It runs inside `coderd` by default and can also run as a [standalone deployment](../../../ai-coder/ai-gateway/standalone.md) that scales independently of the control plane.
Size replicas based on your AI request volume and `CODER_AI_GATEWAY_MAX_CONCURRENCY`.
For the chart's resource requests and autoscaling defaults, refer to the [AI Gateway Helm chart README](../../../../helm/ai-gateway/README.md).

## Kubernetes Infrastructure

Kubernetes is the recommended, and supported platform for deploying Coder in the
enterprise. It is the hosting platform of choice for a large majority of Coder's
Fortune 500 customers, and it is the platform in which we build and test against
here at Coder.

### General recommendations

In general, it is recommended to deploy Coder into its own respective cluster,
separate from production applications. Keep in mind that Coder runs development
workloads, so the cluster should be deployed as such, without production-level
configurations.

### Compute

Deploy your Kubernetes cluster with two node groups, one for Coder's control
plane, and another for user workspaces (if you intend on leveraging K8s for
end-user compute).

#### Control plane nodes

The Coder control plane node group must be static, to prevent scale down events
from dropping pods, and thus dropping user connections to the dashboard UI and
their workspaces.

Coder's Helm Chart supports
[defining nodeSelectors, affinities, and tolerations](https://github.com/coder/coder/blob/e96652ebbcdd7554977594286b32015115c3f5b6/helm/coder/values.yaml#L221-L249)
to schedule the control plane pods on the appropriate node group.

#### Workspace nodes

Coder workspaces can be deployed either as Pods or Deployments in Kubernetes.
See our
[example Kubernetes workspace template](../../../../examples/templates/kubernetes).
Configure the workspace node group to be auto-scaling, to dynamically allocate
compute as users start/stop workspaces at the beginning and end of their day.
Set nodeSelectors, affinities, and tolerations in Coder templates to assign
workspaces to the given node group:

```tf
resource "kubernetes_deployment" "coder" {
  spec {
    template {
      metadata {
        labels = {
          app = "coder-workspace"
        }
      }

      spec {
        affinity {
          pod_anti_affinity {
            preferred_during_scheduling_ignored_during_execution {
              weight = 1
              pod_affinity_term {
                label_selector {
                  match_expressions {
                    key      = "app.kubernetes.io/instance"
                    operator = "In"
                    values   = ["coder-workspace"]
                  }
                }
                topology_key = # add your node group label here
              }
            }
          }
        }

        tolerations {
          # Add your tolerations here
        }

        node_selector {
          # Add your node selectors here
        }

        container {
          image = "coder-workspace:latest"
          name  = "dev"
        }
      }
    }
  }
}
```

#### Node sizing

For sizing recommendations, see the below reference architectures:

- [Up to 1,000 users](./1k-users.md)

- [Up to 2,000 users](./2k-users.md)

- [Up to 3,000 users](./3k-users.md)

- [Up to 10,000 users](./10k-users.md)

### AWS Instance Types

For production AWS deployments, we recommend using non-burstable instance types,
such as `m5` or `c5`, instead of burstable instances, such as `t3`.
Burstable instances can experience significant performance degradation once
CPU credits are exhausted, leading to poor user experience under sustained load.

| Component         | Recommended Instance Type | Reason                                                   |
|-------------------|---------------------------|----------------------------------------------------------|
| coderd nodes      | `m5`                      | Balanced compute and memory for API and UI serving.      |
| Provisioner nodes | `c5`                      | Compute-optimized performance for faster builds.         |
| Workspace nodes   | `m5`                      | Balanced performance for general development workloads.  |
| Database nodes    | `db.m5`                   | Consistent database performance for reliable operations. |

### Networking

It is likely your enterprise deploys Kubernetes clusters with various networking
restrictions. With this in mind, Coder requires the following connectivity:

- Egress from workspace compute to the Coder control plane pods
- Egress from control plane pods to Coder's PostgreSQL database
- Egress from control plane pods to git and package repositories
- Ingress from user devices to the control plane Load Balancer or Ingress
  controller

We recommend configuring your network policies in accordance with the above.
Note that Coder workspaces do not require any ports to be open.

### Storage

If running Coder workspaces as Kubernetes Pods or Deployments, you will need to
assign persistent storage. We recommend leveraging a
[supported Container Storage Interface (CSI) driver](https://kubernetes-csi.github.io/docs/drivers.html)
in your cluster, with Dynamic Provisioning and read/write, to provide on-demand
storage to end-user workspaces.

The following Kubernetes volume types have been validated by Coder internally,
and/or by our customers:

- [PersistentVolumeClaim](https://kubernetes.io/docs/concepts/storage/volumes/#persistentvolumeclaim)
- [NFS](https://kubernetes.io/docs/concepts/storage/volumes/#nfs)
- [subPath](https://kubernetes.io/docs/concepts/storage/volumes/#using-subpath)
- [cephfs](https://kubernetes.io/docs/concepts/storage/volumes/#cephfs)

Our
[example Kubernetes workspace template](https://github.com/coder/coder/blob/5b9a65e5c137232351381fc337d9784bc9aeecfc/examples/templates/kubernetes/main.tf#L191-L219)
provisions a PersistentVolumeClaim block storage device, attached to the
Deployment.

It is not recommended to mount volumes from the host node(s) into workspaces,
for security and reliability purposes. The below volume types are _not_
recommended for use with Coder:

- [Local](https://kubernetes.io/docs/concepts/storage/volumes/#local)
- [hostPath](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath)

Not that Coder's control plane filesystem is ephemeral, so no persistent storage
is required.

## PostgreSQL database

Coder requires access to an external PostgreSQL database to store user data,
workspace state, template files, and more. Depending on the scale of the
user-base, workspace activity, and High Availability requirements, the amount of
CPU and memory resources required by Coder's database may differ.

### Disaster recovery

Prepare internal scripts for dumping and restoring your database. We recommend
scheduling regular database backups, especially before upgrading Coder to a new
release. Coder does not support downgrades without initially restoring the
database to the prior version.

### Performance efficiency

We highly recommend deploying the PostgreSQL instance in the same region (and if possible, same availability zone) as the control plane to optimize for low latency connections.
We recommend keeping latency under 10&nbsp;ms between the control plane and database.

When determining scaling requirements, take into account the following
considerations:

- `2 vCPU x 8 GB RAM x 512 GB storage`: A baseline for database requirements for
  Coder deployment with less than 1000 users, and low activity level (30% active
  users). This capacity should be sufficient to support 100 external
  provisioners.
- Storage size depends on user activity, workspace builds, log verbosity,
  overhead on database encryption, etc.
- Allocate two additional CPU core to the database instance for every 1000
  active users.
- Enable High Availability mode for database engine for large scale deployments.

#### Recommended instance types by cloud provider

For production deployments, we recommend using dedicated compute instances rather than burstable instances (like AWS t-family) which provide inconsistent CPU performance. Below are recommended instance types for each major cloud provider:

##### AWS (RDS/Aurora PostgreSQL)

- **Small deployments (<1000 users)**: `db.m6i.large` (2&nbsp;vCPU, 8&nbsp;GB RAM) or `db.r6i.large` (2&nbsp;vCPU, 16&nbsp;GB RAM)
- **Medium deployments (1000-2000 users)**: `db.m6i.xlarge` (4&nbsp;vCPU, 16&nbsp;GB RAM) or `db.r6i.xlarge` (4&nbsp;vCPU, 32&nbsp;GB RAM)
- **Large deployments (2000+ users)**: `db.m6i.2xlarge` (8&nbsp;vCPU, 32&nbsp;GB RAM) or `db.r6i.2xlarge` (8&nbsp;vCPU, 64&nbsp;GB RAM)

[Comparison](https://instances.vantage.sh/rds?memory_expr=%3E%3D0&vcpus_expr=%3E%3D0&memory_per_vcpu_expr=%3E%3D0&gpu_memory_expr=%3E%3D0&gpus_expr=%3E%3D0&maxips_expr=%3E%3D0&storage_expr=%3E%3D0&filter=db.r6i.large%7Cdb.m6i.large%7Cdb.m6i.xlarge%7Cdb.r6i.xlarge%7Cdb.r6i.2xlarge%7Cdb.m6i.2xlarge&region=us-east-1&pricing_unit=instance&cost_duration=hourly&reserved_term=yrTerm1Standard.noUpfront&compare_on=true)

##### Azure (Azure Database for PostgreSQL)

- **Small deployments (<1000 users)**: `Standard_D2s_v5` (2&nbsp;vCPU, 8&nbsp;GB RAM) or `Standard_E2s_v5` (2&nbsp;vCPU, 16&nbsp;GB RAM)
- **Medium deployments (1000-2000 users)**: `Standard_D4s_v5` (4&nbsp;vCPU, 16&nbsp;GB RAM) or `Standard_E4s_v5` (4&nbsp;vCPU, 32&nbsp;GB RAM)
- **Large deployments (2000+ users)**: `Standard_D8s_v5` (8&nbsp;vCPU, 32&nbsp;GB RAM) or `Standard_E8s_v5` (8&nbsp;vCPU, 64&nbsp;GB RAM)

[Comparison](https://instances.vantage.sh/azure?memory_expr=%3E%3D0&vcpus_expr=%3E%3D0&memory_per_vcpu_expr=%3E%3D0&gpu_memory_expr=%3E%3D0&gpus_expr=%3E%3D0&maxips_expr=%3E%3D0&storage_expr=%3E%3D0&filter=d2s-v5%7Ce2s-v5%7Cd4s-v5%7Ce4s-v5%7Ce8s-v5%7Cd8s-v5&region=us-east&pricing_unit=instance&cost_duration=hourly&reserved_term=yrTerm1Standard.allUpfront&compare_on=true)

##### Google Cloud (Cloud SQL for PostgreSQL)

- **Small deployments (<1000 users)**: `db-perf-optimized-N-2` (2&nbsp;vCPU, 16&nbsp;GB RAM)
- **Medium deployments (1000-2000 users)**: `db-perf-optimized-N-4` (4&nbsp;vCPU, 32&nbsp;GB RAM)
- **Large deployments (2000+ users)**: `db-perf-optimized-N-8` (8&nbsp;vCPU, 64&nbsp;GB RAM)

[Comparison](https://cloud.google.com/sql/docs/postgres/machine-series-overview#n2)

##### Storage recommendations

For optimal database performance, use the following storage types:

- **AWS RDS/Aurora**: Use `gp3` (General Purpose SSD) volumes with at least 3,000 IOPS for production workloads. For high-performance requirements, consider `io1` or `io2` volumes with provisioned IOPS.

- **Azure Database for PostgreSQL**: Use Premium SSD (P-series) with appropriate IOPS and throughput provisioning. Standard SSD can be used for development/test environments.

- **Google Cloud SQL**: Use SSD persistent disks for production workloads. Standard (HDD) persistent disks are suitable only for development or low-performance requirements.

If you enable
[database encryption](../../../admin/security/database-encryption.md) in Coder,
consider allocating an additional CPU core to every `coderd` replica.

#### Resource utilization guidelines

Below are general recommendations for sizing your PostgreSQL instance:

- Increase number of vCPU if CPU utilization or database latency is high.
- Allocate extra memory if database performance is poor, CPU utilization is low,
  and memory utilization is high.
- Utilize faster disk options (higher IOPS) such as SSDs or NVMe drives for
  optimal performance enhancement and possibly reduce database load.

## Operational readiness

Operational readiness in Coder is about ensuring that everything is set up
correctly before launching a platform into production. It involves making sure
that the service is reliable, secure, and easily scales accordingly to user-base
needs. Operational readiness is crucial because it helps prevent issues that
could affect workspace users experience once the platform is live.

### Helm Chart Configuration

1. Reference our
   [Helm chart values file](../../../../helm/coder/values.yaml)
   and identify the required values for deployment.
1. Create a `values.yaml` and add it to your version control system.
1. Determine the necessary environment variables. Here is the
   [full list of supported server environment variables](../../../reference/cli/server/index.md).
1. Follow our documented
   [steps for installing Coder via Helm](../../server/kubernetes/index.md).

### Template configuration

1. Establish dedicated accounts for users with the _Template Administrator_
   role.
1. Maintain Coder templates using
   [version control](../../../admin/templates/managing-templates/change-management.md).
1. Consider implementing a GitOps workflow to automatically push new template
   versions into Coder from git. For example, on GitHub, you can use the
   [Setup Coder](https://github.com/marketplace/actions/setup-coder) action.
1. Evaluate enabling
   [automatic template updates](../../../admin/templates/managing-templates/index.md#template-update-policies)
   upon workspace startup.

### Observability

1. Enable the Prometheus endpoint (environment variable:
   `CODER_PROMETHEUS_ENABLE`).
1. Deploy the
   [Coder Observability bundle](https://github.com/coder/observability) to
   leverage pre-configured dashboards, alerts, and runbooks for monitoring
   Coder. This includes integrations between Prometheus, Grafana, Loki, and
   Alertmanager.
1. Review the [Prometheus response](../../../admin/integrations/prometheus.md) and set up
   alarms on selected metrics.

### User support

1. Incorporate [support links](../../../admin/setup/appearance.md#support-links) into
   internal documentation accessible from the user context menu. Ensure that
   hyperlinks are valid and lead to up-to-date materials.
1. Encourage the use of `coder support bundle` to allow workspace users to
   generate and provide network-related diagnostic data.

---

# Reference architecture: up to 1,000 users

Source: https://coder.com/docs/install/plan/sizing/1k-users

The 1,000 users architecture is designed to cover a wide range of workflows.
Examples of subjects that might utilize this architecture include medium-sized
tech startups, educational units, or small to mid-sized enterprises.

The recommendations on this page apply to deployments with up to the following limits. If your needs
exceed any of these limits, consider increasing deployment resources or moving to the [next-higher
architectural tier](./2k-users.md).

| Users | Concurrent Running Workspaces | Concurrent Builds |
|-------|-------------------------------|-------------------|
| 1000  | 600                           | 60                |

## Hardware recommendations

### Coderd

| vCPU | Memory    | Replicas |
|------|-----------|----------|
| 2    | 8&nbsp;GB | 3        |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `2000m`
  - Set Memory request and limit to `8Gi`
- `coderd` does not typically benefit from high performance disks like SSDs (unless you are co-locating provisioners).
- For small deployments (ca. 100 users, 10 concurrent workspace builds), it is
  acceptable to deploy provisioners on `coderd` replicas.
- `coderd` instances should be deployed in the same region as the database.

### Provisioners

| vCPU | Memory    | Replicas |
|------|-----------|----------|
| 1    | 1&nbsp;GB | 60       |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `1000m`
  - Set Memory request and limit to `1Gi`
- If deploying on virtual machines, stack up to 30 provisioners per machine with a commensurate amount of memory and CPU.
- Provisioners benefit from high performance disks like SSDs.
- For small deployments (ca. 100 users, 10 concurrent workspace builds), it is
  acceptable to deploy provisioners on `coderd` nodes.
- If deploying workspaces to multiple clouds or multiple Kubernetes clusters, divide the provisioner replicas among the
  clouds or clusters according to expected usage.

### Database

| vCPU | Memory     | Replicas |
|------|------------|----------|
| 8    | 30&nbsp;GB | 1        |

**Notes**:

- "General purpose" virtual machines, such as the M8-series in AWS work well.
- Deploy in the same region as `coderd`

### Workspaces

The following resource requirements are for the Coder Workspace Agent, which runs alongside your end users work, and as
such should be interpreted as the _bare minimum_ requirements for a Coder workspace. Size your workspaces to fit the use
case your users will be undertaking. If in doubt, chose sizes based on the development environments your users are
migrating from onto Coder.

| vCPU | Memory      |
|------|-------------|
| 0.1  | 128&nbsp;MB |

## Footnotes for AWS instance types

- For production deployments, we recommend using non-burstable instance types,
  such as `m5` or `c5`, instead of burstable instances, such as `t3`.
  Burstable instances can experience significant performance degradation once
  CPU credits are exhausted, leading to poor user experience under sustained load.

---

# Reference architecture: up to 2,000 users

Source: https://coder.com/docs/install/plan/sizing/2k-users

In the 2,000 users architecture, there is a moderate increase in traffic,
suggesting a growing user base or expanding operations. This setup is
well-suited for mid-sized companies experiencing growth or for universities
seeking to accommodate their expanding user populations.

The recommendations on this page apply to deployments with up to the following limits. If your needs
exceed any of these limits, consider increasing deployment resources or moving to the [next-higher
architectural tier](./3k-users.md).

| Users | Concurrent Running Workspaces | Concurrent Builds |
|-------|-------------------------------|-------------------|
| 2000  | 1200                          | 120               |

**Observability**: Deploy monitoring solutions to gather Prometheus metrics and
visualize them with Grafana to gain detailed insights into infrastructure and
application behavior. This allows operators to respond quickly to incidents and
continuously improve the reliability and performance of the platform.

## Hardware recommendations

### Coderd

| vCPU | Memory     | Replicas |
|------|------------|----------|
| 4    | 12&nbsp;GB | 3        |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `4000m`
  - Set Memory request and limit to `12Gi`
- `coderd` does not typically benefit from high performance disks like SSDs (unless you are co-locating provisioners).
- `coderd` instances should be deployed in the same region as the database.

### Workspace Proxies

If you choose to deploy workspaces in multiple geographic regions, provision
[Workspace Proxies](../../../admin/networking/workspace-proxies.md) in each region.

| vCPU | Memory     | Replicas |
|------|------------|----------|
| 4    | 12&nbsp;GB | 3        |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `4000m`
  - Set Memory request and limit to `12Gi`
- Workspace Proxies do not typically benefit from high performance disks like SSDs.

### Provisioners

| vCPU | Memory    | Replicas |
|------|-----------|----------|
| 1    | 1&nbsp;GB | 120      |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `1000m`
  - Set Memory request and limit to `1Gi`
- If deploying on virtual machines, stack up to 30 provisioners per machine with a commensurate amount of memory and CPU.
- Provisioners benefit from high performance disks like SSDs.
- [Do not run provisioners on `coderd` nodes](../../operate/provisioners/index.md#disable-built-in-provisioners) at this scale.
- If deploying workspaces to multiple clouds or multiple Kubernetes clusters, divide the provisioner replicas among the
  clouds or clusters according to expected usage.

### Database

| vCPU | Memory     | Replicas |
|------|------------|----------|
| 16   | 60&nbsp;GB | 1        |

**Notes**:

- "General purpose" virtual machines, such as the M8-series in AWS work well.
- Deploy in the same region as `coderd`

### Workspaces

The following resource requirements are for the Coder Workspace Agent, which runs alongside your end users work, and as
such should be interpreted as the _bare minimum_ requirements for a Coder workspace. Size your workspaces to fit the use
case your users will be undertaking. If in doubt, chose sizes based on the development environments your users are
migrating from onto Coder.

| vCPU | Memory      |
|------|-------------|
| 0.1  | 128&nbsp;MB |

## Footnotes for AWS instance types

- For production deployments, we recommend using non-burstable instance types,
  such as `m5` or `c5`, instead of burstable instances, such as `t3`.
  Burstable instances can experience significant performance degradation once
  CPU credits are exhausted, leading to poor user experience under sustained load.

---

# Reference architecture: up to 3,000 users

Source: https://coder.com/docs/install/plan/sizing/3k-users

The 3,000 users architecture targets large-scale enterprises, possibly with
on-premises network and cloud deployments.

The recommendations on this page apply to deployments with up to the following limits. If your needs
exceed any of these limits, consider increasing deployment resources or moving to the [next-higher
architectural tier](./10k-users.md).

| Users | Concurrent Running Workspaces | Concurrent Builds |
|-------|-------------------------------|-------------------|
| 3000  | 1800                          | 180               |

**Observability**: Deploy monitoring solutions to gather Prometheus metrics and
visualize them with Grafana to gain detailed insights into infrastructure and
application behavior. This allows operators to respond quickly to incidents and
continuously improve the reliability and performance of the platform.

## Hardware recommendations

### Coderd

| vCPU | Memory     | Replicas |
|------|------------|----------|
| 4    | 12&nbsp;GB | 4        |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `4000m`
  - Set Memory request and limit to `12Gi`
- `coderd` does not typically benefit from high performance disks like SSDs (unless you are co-locating provisioners).
- `coderd` instances should be deployed in the same region as the database.

### Workspace Proxies

If you choose to deploy workspaces in multiple geographic regions, provision
[Workspace Proxies](../../../admin/networking/workspace-proxies.md) in each region.

| vCPU | Memory     | Replicas |
|------|------------|----------|
| 4    | 12&nbsp;GB | 4        |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `4000m`
  - Set Memory request and limit to `12Gi`
- Workspace Proxies do not typically benefit from high performance disks like SSDs.

### Provisioners

| vCPU | Memory    | Replicas |
|------|-----------|----------|
| 1    | 1&nbsp;GB | 180      |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `1000m`
  - Set Memory request and limit to `1Gi`
- If deploying on virtual machines, stack up to 30 provisioners per machine with a commensurate amount of memory and CPU.
- Provisioners benefit from high performance disks like SSDs.
- [Do not run provisioners on `coderd` nodes](../../operate/provisioners/index.md#disable-built-in-provisioners) at this scale.
- If deploying workspaces to multiple clouds or multiple Kubernetes clusters, divide the provisioner replicas among the
  clouds or clusters according to expected usage.

### Database

| vCPU | Memory      | Replicas |
|------|-------------|----------|
| 32   | 120&nbsp;GB | 1        |

**Notes**:

- "General purpose" virtual machines, such as the M8-series in AWS work well.
- Deploy in the same region as `coderd`

### Workspaces

The following resource requirements are for the Coder Workspace Agent, which runs alongside your end users work, and as
such should be interpreted as the _bare minimum_ requirements for a Coder workspace. Size your workspaces to fit the use
case your users will be undertaking. If in doubt, chose sizes based on the development environments your users are
migrating from onto Coder.

| vCPU | Memory      |
|------|-------------|
| 0.1  | 128&nbsp;MB |

## Footnotes for AWS instance types

- For production deployments, we recommend using non-burstable instance types,
  such as `m5` or `c5`, instead of burstable instances, such as `t3`.
  Burstable instances can experience significant performance degradation once
  CPU credits are exhausted, leading to poor user experience under sustained load.

---

# Reference architecture: up to 10,000 users

Source: https://coder.com/docs/install/plan/sizing/10k-users

The 10,000 users architecture targets enterprises with an extremely large global workforce of technical professionals or
applications requiring lots of simultaneous workspaces (for example, Agentic AI).

The recommendations on this page apply to deployments with up to the following limits. If your needs
exceed any of these limits, consider increasing deployment resources.

| Users | Concurrent Running Workspaces | Concurrent Builds |
|-------|-------------------------------|-------------------|
| 10000 | 6000                          | 600               |

**Observability**: Deploy monitoring solutions to gather Prometheus metrics and
visualize them with Grafana to gain detailed insights into infrastructure and
application behavior. This allows operators to respond quickly to incidents and
continuously improve the reliability and performance of the platform.

## Hardware recommendations

### Coderd

| vCPU | Memory     | Replicas |
|------|------------|----------|
| 4    | 12&nbsp;GB | 10       |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `4000m`
  - Set Memory request and limit to `12Gi`
- `coderd` does not typically benefit from high performance disks like SSDs (unless you are co-locating provisioners).
- `coderd` instances should be deployed in the same region as the database.

### Workspace Proxies

If you choose to deploy workspaces in multiple geographic regions, provision
[Workspace Proxies](../../../admin/networking/workspace-proxies.md) in each region.

| vCPU | Memory     | Replicas |
|------|------------|----------|
| 4    | 12&nbsp;GB | 10       |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `4000m`
  - Set Memory request and limit to `12Gi`
- Workspace Proxies do not typically benefit from high performance disks like SSDs.

### Provisioners

| vCPU | Memory    | Replicas |
|------|-----------|----------|
| 1    | 1&nbsp;GB | 600      |

**Notes**:

- "General purpose" virtual machines, such as N4-series in GCP or M8-series in AWS work well.
- If deploying on Kubernetes:
  - Set CPU request and limit to `1000m`
  - Set Memory request and limit to `1Gi`
- If deploying on virtual machines, stack up to 30 provisioners per machine with a commensurate amount of memory and CPU.
- Provisioners benefit from high performance disks like SSDs.
- [Do not run provisioners on `coderd` nodes](../../operate/provisioners/index.md#disable-built-in-provisioners) at this scale.
- If deploying workspaces to multiple clouds or multiple Kubernetes clusters, divide the provisioner replicas among the
  clouds or clusters according to expected usage.

### Database

| vCPU | Memory      | Replicas |
|------|-------------|----------|
| 64   | 240&nbsp;GB | 1        |

**Notes**:

- "General purpose" virtual machines, such as the M8-series in AWS work well.
- Deploy in the same region as `coderd`

### Workspaces

The following resource requirements are for the Coder Workspace Agent, which runs alongside your end users work, and as
such should be interpreted as the _bare minimum_ requirements for a Coder workspace. Size your workspaces to fit the use
case your users will be undertaking. If in doubt, chose sizes based on the development environments your users are
migrating from onto Coder.

| vCPU | Memory      |
|------|-------------|
| 0.1  | 128&nbsp;MB |

## Footnotes for AWS instance types

- For production deployments, we recommend using non-burstable instance types,
  such as `m5` or `c5`, instead of burstable instances, such as `t3`.
  Burstable instances can experience significant performance degradation once
  CPU credits are exhausted, leading to poor user experience under sustained load.

---

# 2. Prepare prerequisites

Source: https://coder.com/docs/install/prepare

Preparation gathers the external pieces a deployment depends on.
Most of them are owned by another team, so their lead time, not the installation itself, usually sets your timeline.
Start the slowest items first.

## What to gather

| Prerequisite                        | Usual owner                     | Notes                                                                                                                                           |
|-------------------------------------|---------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| Access hostname and DNS records     | DNS and TLS owner               | You need the Coder hostname, and a wildcard record if you want to serve workspace apps on subdomains                                            |
| TLS certificates                    | DNS and TLS owner               | A wildcard certificate covers the hostname and the workspace app subdomains                                                                     |
| PostgreSQL database                 | Database administrator          | Include a backup and restore plan, not only a connection string                                                                                 |
| Identity provider application       | Identity provider administrator | Register the OIDC or SAML application and agree on the group claims you intend to map                                                           |
| Coder license                       | Licensing contact               | Required for Premium features; refer to [Licensing](./licensing.md)                                                                             |
| Container images and Coder binaries | Coder platform owner            | Only for restricted networks; refer to [Air-gapped deployments](./airgap.md) and [Mirror Coder Registry with Artifactory](./registry-mirror.md) |

## Lead times

Certificates, database provisioning, and identity provider registration are the items most likely to block an install, because each one needs a request to another team and a review cycle.
Requesting them while you're still planning is usually the difference between a deployment that takes days and one that takes weeks.

## Before you move on

You can install the control plane without every item on this list, and a proof of concept often does.
Treat the list as strong recommendations: each item you skip is work that reappears later, usually when real users already depend on the deployment.

Next: [Install the control plane](../server/index.md).

<children></children>

---

# Licensing

Source: https://coder.com/docs/install/prepare/licensing

Some features are only accessible with a Premium license, including
[AI Governance](../../ai-coder/ai-governance.md). See our
[pricing page](https://coder.com/pricing) for more details. To try paid
features, you can [request a trial](https://coder.com/trial) or
[contact sales](https://coder.com/contact).

![Licenses screen shows license information and seat consumption](../../images/admin/licenses/licenses-screen.png)

## Offline license validation

Coder license keys are signed JWTs that are validated locally using cryptographic
signatures. No outbound connection to Coder's servers is required for license
validation. This means licenses work in
[air-gapped and offline deployments](./airgap.md) without any
additional configuration.

<a id="adding-your-license-key"></a>

## Add your license key

There are two ways to add a license to a Coder deployment:

<div class="tabs">

### Coder UI

1. With an `Owner` account, go to **Admin settings** > **Deployment**.

1. Select **Licenses** from the sidebar, then **Add a license**:

   ![Add a license from the licenses screen](../../images/admin/licenses/licenses-nolicense.png)

1. On the **Add a license** screen, drag your `.jwt` license file into the
   **Upload Your License** section, or paste your license in the
   **Paste Your License** text box, then select **Upload License**:

   ![Add a license screen](../../images/admin/licenses/add-license-ui.png)

### Coder CLI

1. Ensure you have the [Coder CLI](../cli.md) installed.
1. Save your license key to disk and make note of the path.
1. Open a terminal.
1. Log in to your Coder deployment:

   ```sh
   coder login <access url>
   ```

1. Run `coder licenses add`:

   - For a `.jwt` license file:

     ```sh
     coder licenses add -f <path to your license key>
     ```

   - For a text string:

     ```sh
     coder licenses add -l 1f5...765
     ```

</div>

## FAQ

### Find your deployment ID

You'll need your deployment ID to request a trial or license key.

From your Coder dashboard, select your user avatar, then select the **Copy to
clipboard** icon at the bottom:

![Copy the deployment ID from the bottom of the user avatar dropdown](../../images/admin/deployment-id-copy-clipboard.png)

### How we calculate license seat consumption

Licenses are consumed based on the status of user accounts.
Only users who have been active in the last 90&nbsp;days consume license seats.

Consult the [user status documentation](../../admin/users/index.md#user-status) for more information about active, dormant, and suspended user statuses.

---

# Air-gapped Deployments

Source: https://coder.com/docs/install/prepare/airgap

All Coder features are supported in air-gapped / behind firewalls / disconnected / offline.
This is a general comparison. Keep reading for a full tutorial running Coder
air-gapped with Kubernetes or Docker.

|                           | Public deployments                                                                                                                                                                                                                                                 | Air-gapped deployments                                                                                                                                                                                                                                                                                                    |
|---------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Terraform binary          | By default, Coder downloads Terraform binary from [releases.hashicorp.com](https://releases.hashicorp.com)                                                                                                                                                         | Terraform binary must be included in `PATH` for the VM or container image. [Supported versions](../../../provisioner/terraform/install.go#L27-L28)                                                                                                                                                                        |
| Terraform registry        | Coder templates will attempt to download providers from [registry.terraform.io](https://registry.terraform.io) or [custom source addresses](https://developer.hashicorp.com/terraform/language/providers/requirements#source-addresses) specified in each template | [Custom source addresses](https://developer.hashicorp.com/terraform/language/providers/requirements#source-addresses) can be specified in each Coder template, or a custom registry/mirror can be used. More details below                                                                                                |
| STUN                      | By default, Coder uses Google's public STUN server for direct workspace connections                                                                                                                                                                                | STUN can be safely [disabled](../../reference/cli/server/index.md#--derp-server-stun-addresses) users can still connect via [relayed connections](../../admin/networking/index.md#-geo-distribution). Alternatively, you can set a [custom DERP server](../../reference/cli/server/index.md#--derp-server-stun-addresses) |
| DERP                      | By default, Coder's built-in DERP relay can be used, or [Tailscale's public relays](../../admin/networking/index.md#relayed-connections).                                                                                                                          | By default, Coder's built-in DERP relay can be used, or [custom relays](../../admin/networking/index.md#custom-relays).                                                                                                                                                                                                   |
| PostgreSQL                | If no [PostgreSQL connection URL](../../reference/cli/server/index.md#--postgres-url) is specified, Coder will download Postgres from [repo1.maven.org](https://repo1.maven.org)                                                                                   | An external database is required, you must specify a [PostgreSQL connection URL](../../reference/cli/server/index.md#--postgres-url)                                                                                                                                                                                      |
| Telemetry                 | Telemetry is on by default, and [can be disabled](../../reference/cli/server/index.md#--telemetry)                                                                                                                                                                 | Telemetry [can be disabled](../../reference/cli/server/index.md#--telemetry)                                                                                                                                                                                                                                              |
| Update check              | By default, Coder checks for updates from [GitHub releases](https://github.com/coder/coder/releases)                                                                                                                                                               | Update checks [can be disabled](../../reference/cli/server/index.md#--update-check)                                                                                                                                                                                                                                       |
| License validation        | License keys are validated locally using cryptographic signatures. No outbound connection to Coder is required                                                                                                                                                     | No changes needed. See [offline license validation](./licensing.md#offline-license-validation)                                                                                                                                                                                                                            |
| AI Governance Usage Count | By default, deployments with [AI Governance](../../ai-coder/ai-governance.md) report usage data                                                                                                                                                                    | [Contact us](https://coder.com/contact) to request a license with usage reporting off.                                                                                                                                                                                                                                    |

## Air-gapped container images

The following instructions walk you through how to build a custom control plane
image for Docker or Kubernetes

First, build and push a container image extending our official image with the
following:

- CLI config (.tfrc) for Terraform referring to
  [external mirror](https://www.terraform.io/cli/config/config-file#explicit-installation-method-configuration)
- [Terraform Providers](https://registry.terraform.io) for templates
  - These could also be specified via a volume mount (Docker) or
    [network mirror](https://www.terraform.io/internals/provider-network-mirror-protocol).
    See below for details.

> [!NOTE]
> Coder includes the latest
> [supported version](../../../provisioner/terraform/install.go#L27-L28)
> of Terraform in the official Docker images. If you need to bundle a different
> version of terraform, you can do so by customizing the image.

Here's an example Dockerfile:

```dockerfile
FROM ghcr.io/coder/coder:latest

USER root

RUN apk add curl unzip

# Create directory for the Terraform CLI (and assets)
RUN mkdir -p /opt/terraform

# Terraform is already included in the official Coder image.
# See ../../scripts/Dockerfile.base#L15
# If you need to install a different version of Terraform, you can do so here.
# The below step is optional if you wish to keep the existing version.
# See ../../provisioner/terraform/install.go#L27-L28
# for supported Terraform versions.
ARG TERRAFORM_VERSION=1.11.0
RUN apk update && \
    curl -LOs https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
    && unzip -o terraform_${TERRAFORM_VERSION}_linux_amd64.zip \
    && mv terraform /opt/terraform \
    && rm terraform_${TERRAFORM_VERSION}_linux_amd64.zip
ENV PATH=/opt/terraform:${PATH}

# Additionally, a Terraform mirror needs to be configured
# to download the Terraform providers used in Coder templates.
# There are two options:

# Option 1) Use a filesystem mirror.
#  We can seed this at build-time or by mounting a volume to
#  /opt/terraform/plugins in the container.
#  https://developer.hashicorp.com/terraform/cli/config/config-file#filesystem_mirror
#  Be sure to add all the providers you use in your templates to /opt/terraform/plugins

RUN mkdir -p /home/coder/.terraform.d/plugins/registry.terraform.io
ADD filesystem-mirror-example.tfrc /home/coder/.terraformrc

# Optionally, we can "seed" the filesystem mirror with common providers.
# Comment out lines 40-49 if you plan on only using a volume or network mirror:
WORKDIR /home/coder/.terraform.d/plugins/registry.terraform.io
ARG CODER_PROVIDER_VERSION=2.2.0
RUN echo "Adding coder/coder v${CODER_PROVIDER_VERSION}" \
    && mkdir -p coder/coder && cd coder/coder \
    && curl -LOs https://github.com/coder/terraform-provider-coder/releases/download/v${CODER_PROVIDER_VERSION}/terraform-provider-coder_${CODER_PROVIDER_VERSION}_linux_amd64.zip
ARG DOCKER_PROVIDER_VERSION=3.0.2
RUN echo "Adding kreuzwerker/docker v${DOCKER_PROVIDER_VERSION}" \
    && mkdir -p kreuzwerker/docker && cd kreuzwerker/docker \
    && curl -LOs https://github.com/kreuzwerker/terraform-provider-docker/releases/download/v${DOCKER_PROVIDER_VERSION}/terraform-provider-docker_${DOCKER_PROVIDER_VERSION}_linux_amd64.zip
ARG KUBERNETES_PROVIDER_VERSION=2.36.0
RUN echo "Adding kubernetes/kubernetes v${KUBERNETES_PROVIDER_VERSION}" \
    && mkdir -p hashicorp/kubernetes && cd hashicorp/kubernetes \
    && curl -LOs https://releases.hashicorp.com/terraform-provider-kubernetes/${KUBERNETES_PROVIDER_VERSION}/terraform-provider-kubernetes_${KUBERNETES_PROVIDER_VERSION}_linux_amd64.zip
ARG AWS_PROVIDER_VERSION=5.89.0
RUN echo "Adding aws/aws v${AWS_PROVIDER_VERSION}" \
    && mkdir -p aws/aws && cd aws/aws \
    && curl -LOs https://releases.hashicorp.com/terraform-provider-aws/${AWS_PROVIDER_VERSION}/terraform-provider-aws_${AWS_PROVIDER_VERSION}_linux_amd64.zip

RUN chown -R coder:coder /home/coder/.terraform*
WORKDIR /home/coder

# Option 2) Use a network mirror.
#  https://developer.hashicorp.com/terraform/cli/config/config-file#network_mirror
#  Be sure uncomment line 60 and edit network-mirror-example.tfrc to
#  specify the HTTPS base URL of your mirror.

# ADD network-mirror-example.tfrc /home/coder/.terraformrc

USER coder

# Use the .terraformrc file to inform Terraform of the locally installed providers.
ENV TF_CLI_CONFIG_FILE=/home/coder/.terraformrc
```

> [!NOTE]
> If you are bundling Terraform providers into your Coder image, be sure the
> provider version matches any templates or
> [example templates](../../../examples/templates)
> you intend to use.

```tf
# filesystem-mirror-example.tfrc
provider_installation {
  filesystem_mirror {
    path = "/home/coder/.terraform.d/plugins"
  }
}
```

```tf
# network-mirror-example.tfrc
provider_installation {
  network_mirror {
    url = "https://terraform.example.com/providers/"
  }
}
```

<div class="tabs">

### Docker

Follow our [docker-compose](../server/docker.md#install-coder-via-docker-compose)
documentation and modify the docker-compose file to specify your custom Coder
image. Additionally, you can add a volume mount to add providers to the
filesystem mirror without re-building the image.

First, create an empty plugins directory:

```sh
mkdir $HOME/plugins
```

Next, add a volume mount to compose.yaml:

```sh
vim compose.yaml
```

```yaml
# compose.yaml
services:
  coder:
    image: registry.example.com/coder:latest
    volumes:
      - ./plugins:/opt/terraform/plugins
    # ...
  environment:
    CODER_TELEMETRY_ENABLE: "false" # Disable telemetry
    CODER_BLOCK_DIRECT: "true" # force SSH traffic through control plane's DERP proxy
    CODER_DERP_SERVER_STUN_ADDRESSES: "disable" # Only use relayed connections
    CODER_UPDATE_CHECK: "false" # Disable automatic update checks
  database:
    image: registry.example.com/postgres:17
    # ...
```

The
[terraform providers mirror](https://www.terraform.io/cli/commands/providers/mirror)
command can be used to download the required plugins for a Coder template.
This can be uploaded into the `plugins` directory on your offline server.

### Kubernetes

We publish the Helm chart for download on
[GitHub Releases](https://github.com/coder/coder/releases/latest). Follow our
[Kubernetes](../server/kubernetes/index.md) documentation and modify the Helm values to
specify your custom Coder image.

```yaml
# values.yaml
coder:
  image:
    repo: "registry.example.com/coder"
    tag: "latest"
  env:
    # Disable telemetry
    - name: "CODER_TELEMETRY_ENABLE"
      value: "false"
    # Disable automatic update checks
    - name: "CODER_UPDATE_CHECK"
      value: "false"
    # force SSH traffic through control plane's DERP proxy
    - name: CODER_BLOCK_DIRECT
      value: "true"
    # Only use relayed connections
    - name: "CODER_DERP_SERVER_STUN_ADDRESSES"
      value: "disable"
    # You must set up an external PostgreSQL database
    - name: "CODER_PG_CONNECTION_URL"
      value: ""
# ...
```

</div>

## Air-gapped docs

Coder also provides air-gapped documentation in case you want to host it on your
own server. The docs are exported as static files that you can host on any web
server, as demonstrated in the example below:

1. Go to the release page. In this case, we want to use the
   [latest version](https://github.com/coder/coder/releases/latest).
2. Download the documentation files from the "Assets" section. It is named as
   `coder_docs_<version>.tgz`.
3. Extract the file and move its contents to your server folder.
4. If you are using NodeJS, you can execute the following command:
   `cd docs && npx http-server .`
5. Set the [CODER_DOCS_URL](../../reference/cli/server/index.md#--docs-url) environment
   variable to use the URL of your hosted docs. This way, the Coder UI will
   reference the documentation from your specified URL.

With these steps, you'll have the Coder documentation hosted on your server and
accessible for your team to use.

## Template builder

The template builder requires outbound access to `registry.coder.com` for
`terraform init` to resolve module sources at template composition time.

For fully air-gapped deployments, disable the template builder:

```sh
CODER_DISABLE_TEMPLATE_BUILDER=true
```

When the builder is disabled, template creation falls back to the standard
upload and CLI workflows. The **New Template** button on the **Templates** page
links to the starter templates page instead of the builder.

For deployments using a self-hosted module registry mirror, set the registry URL
instead of disabling the builder:

```sh
CODER_TEMPLATE_BUILDER_REGISTRY_URL=registry.internal.example.com
```

This makes the builder generate module source paths pointing at your mirror
rather than `registry.coder.com`.

The value is a bare host, optionally with a port (for example, `mirror.internal:8443`).
A leading `http(s)://` scheme and trailing slash are stripped, and a path, query, fragment, or credentials is rejected at server start.

For a complete walkthrough of setting up the mirror, see
[Mirror the Coder Registry with JFrog Artifactory](./registry-mirror.md).

## Coder Modules

To use Coder modules in offline installations, you can either:

- [Mirror the Coder Registry with JFrog Artifactory](./registry-mirror.md) (recommended)
- [Manually publish modules to Artifactory or use a private git repository](../../admin/templates/extending-templates/modules.md#offline-installations)

## Firewall exceptions

In restricted internet networks, Coder may require connection to internet.
Ensure that the following web addresses are accessible from the machine where
Coder is installed.

- code-server.dev (install via AUR)
- open-vsx.org (optional if someone would use code-server)
- registry.terraform.io (to create and push template)
- v2-licensor.coder.com (developing Coder in Coder)

## JetBrains IDEs

Gateway, JetBrains' remote development product that works with Coder,
[has documented offline deployment steps.](../../admin/templates/extending-templates/jetbrains-airgapped.md)

## Microsoft VS Code Remote - SSH

Installation of the
[Visual Studio Code Remote - SSH extension](https://code.visualstudio.com/docs/remote/ssh)
(for connecting a local VS Code to a remote Coder workspace) requires that your
local machine has outbound HTTPS (port 443) connectivity to:

- update.code.visualstudio.com
- vscode.blob.core.windows.net
- \*.vo.msecnd.net

## Next steps

- [Create your first template](../../tutorials/template-from-scratch.md)
- [Control plane configuration](../../admin/setup/index.md)

---

# Mirror the Coder Registry with JFrog Artifactory

Source: https://coder.com/docs/install/prepare/registry-mirror

This guide shows you how to use JFrog Artifactory to mirror the
[Coder Registry](https://registry.coder.com) for air-gapped or restricted
network deployments.

By configuring Artifactory as a Remote Terraform Repository, you can:

- **Proxy and cache** all Coder modules automatically
- **Keep modules updated** without manual synchronization
- **Support offline access** once modules are cached

## Prerequisites

- JFrog Artifactory instance (Cloud or self-hosted)
- Admin access to create repositories
- Artifactory user token for Terraform authentication

## Step 1: Create the Remote Terraform Repository

1. In Artifactory, go to **Administration > Repositories > Remote**

1. Select **New Remote Repository** and select **Terraform** as the package type

1. Configure the repository with these settings:

   | Setting                | Value                        |
   |------------------------|------------------------------|
   | Repository Key         | `coder-registry`             |
   | URL                    | `https://registry.coder.com` |
   | Terraform Registry URL | `https://registry.coder.com` |

1. Select **Create Remote Repository**

## Step 2: Verify the Repository Configuration

Test that Artifactory can proxy the Coder registry by querying the module
versions API:

```sh
curl -u '<username>:<token>' \
  'https://<your-artifactory-host>/artifactory/api/terraform/coder-registry/v1/modules/coder/code-server/coder/versions'
```

You should see a JSON response listing all available versions of the
`code-server` module.

## Step 3: Configure Terraform CLI

Create or update your Terraform CLI configuration file to use Artifactory.

On Linux/macOS, create `~/.terraformrc`. On Windows, create `%APPDATA%\terraform.rc`.

```tf
host "<your-artifactory-host>" {
  services = {
    "modules.v1" = "https://<your-artifactory-host>/artifactory/api/terraform/coder-registry/v1/modules/"
  }
}

credentials "<your-artifactory-host>" {
  token = "<your-artifactory-token>"
}
```

Replace:

- `<your-artifactory-host>` with your Artifactory hostname (e.g.,
  `artifactory.example.com` or `mycompany.jfrog.io`)
- `<your-artifactory-token>` with your Artifactory access token with read permissions to the `coder-registry` repository

> [!NOTE]
> The `host` block with `services` is required because Artifactory's global
> service discovery endpoint doesn't include the repository name in the modules
> path. This explicitly tells Terraform where to find modules in your specific
> repository.

## Step 4: Update Template Module Sources

Update your Coder templates to use Artifactory instead of the public registry:

```tf
# Before: Direct from Coder registry
module "code-server" {
  source   = "registry.coder.com/coder/code-server/coder"
  version  = "1.4.2"
  agent_id = coder_agent.main.id
}

# After: Through Artifactory mirror
module "code-server" {
  source   = "https://<your-artifactory-host>/coder/code-server/coder"
  version  = "1.4.2"
  agent_id = coder_agent.main.id
}
```

## Step 5: Configure the control plane or provisioners

For Coder to use the Artifactory mirror, configure the Terraform CLI on your
control plane or external provisioners.

<div class="tabs">

### Kubernetes Deployment

Create a secret with the Terraform configuration:

```sh
kubectl create secret generic terraform-config \
  --from-file=.terraformrc=./terraformrc \
  -n coder
```

Update your Helm values:

```yaml
coder:
  volumes:
    - name: terraform-config
      secret:
        secretName: terraform-config
  volumeMounts:
    - name: terraform-config
      mountPath: /home/coder/.terraformrc
      subPath: .terraformrc
      readOnly: true
  env:
    - name: TF_CLI_CONFIG_FILE
      value: /home/coder/.terraformrc
```

### Docker Deployment

Mount the `.terraformrc` file into the Coder container:

```yaml
# docker-compose.yaml
services:
  coder:
    volumes:
      - ./terraformrc:/home/coder/.terraformrc:ro
    environment:
      TF_CLI_CONFIG_FILE: /home/coder/.terraformrc
```

</div>

## Step 6: Point the template builder at your mirror

The [template builder](../../admin/templates/creating-templates.md) resolves module
sources against `registry.coder.com` by default. To make it generate module
source paths that point at your Artifactory mirror instead, set the
`CODER_TEMPLATE_BUILDER_REGISTRY_URL` environment variable on your control plane:

```sh
CODER_TEMPLATE_BUILDER_REGISTRY_URL=<your-artifactory-host>
```

The value is a bare host, optionally with a port (for example,
`artifactory.example.com` or `mycompany.jfrog.io:8443`). A leading `http(s)://`
scheme and trailing slash are stripped, and a path, query, fragment, or
credentials is rejected at server start.

Without this variable, the template builder still requires outbound access to
`registry.coder.com`. For fully air-gapped deployments that cannot set a mirror,
disable the builder instead with `CODER_DISABLE_TEMPLATE_BUILDER=true`. See
[Air-gapped Deployments](./airgap.md#template-builder) for details.

## Caching Behavior

Artifactory uses **lazy caching**, meaning modules are cached on first request.
For fully air-gapped deployments, pre-warm the cache while connected to the
internet:

1. Create a test template that references all modules you need
1. Run `terraform init` to trigger downloads
1. Verify modules appear in Artifactory under `coder-registry-cache`

Once cached, modules remain available even without internet connectivity.

## Supported Namespaces

The Artifactory mirror supports all namespaces from the Coder registry:

| Namespace    | Description               | Example Module                     |
|--------------|---------------------------|------------------------------------|
| `coder`      | Official Coder modules    | `code-server`, `jetbrains-gateway` |
| `coder-labs` | Experimental modules      | `cursor-cli`, `copilot`            |
| Community    | Third-party contributions | Various                            |

All modules use the same source format:

```tf
source = "<your-artifactory-host>/<namespace>/<module>/coder"
```

## Troubleshooting

### Module not found errors

Verify your `.terraformrc` includes both the `host` block with `services` and
the `credentials` block. The `host.services` configuration is required for
Artifactory.

### 401 Unauthorized errors

Check that your Artifactory token is valid and has read access to the
`coder-registry` repository.

### Modules not caching

Ensure the remote repository URL is set to `https://registry.coder.com` and not other paths.

## Next Steps

- [Coder Module Registry](https://registry.coder.com/modules)
- [JFrog Terraform Registry Documentation](https://jfrog.com/help/r/jfrog-artifactory-documentation/terraform-opentofu-and-terraform-backend-repositories)
- [Air-gapped Deployments](./airgap.md)

---

# 3. Install the control plane

Source: https://coder.com/docs/install/server

The pages in this section are alternatives, not sequential steps.
Choose the one that matches the platform your team already operates, or intends to operate, then follow it through to the end.

## Choose a platform

| Platform                                    | Best suited to                                                               |
|---------------------------------------------|------------------------------------------------------------------------------|
| [Kubernetes](./kubernetes/index.md)         | Production deployments, including high availability with multiple replicas   |
| [Rancher](./rancher.md)                     | Kubernetes clusters your team already manages through Rancher                |
| [OpenShift](./openshift.md)                 | Red Hat OpenShift clusters, which need specific security context settings    |
| [Docker](./docker.md)                       | A single machine, such as a proof of concept or a small team deployment      |
| [RPM (RHEL family)](./rpm.md)               | A single Red Hat Enterprise Linux host, or another RHEL-family distribution  |
| [Cloud providers](./cloud/index.md)         | A virtual machine on AWS, Google Cloud, or Azure, or a marketplace listing   |
| [Community install methods](./community.md) | Platforms Coder doesn't package, where a community-contributed method exists |

If your platform choice is still open, size the deployment first in [Plan your deployment](../plan/index.md).
The [Coder Validated Architecture](../plan/sizing/index.md) reference designs assume Kubernetes, which is the recommended platform for deployments that others depend on.

## Before you move on

At the end of this phase you should be able to reach the Coder access URL, sign in as the first administrator, and see the deployment reported as healthy.
If you prepared a license and an identity provider application in [Prepare prerequisites](../prepare/index.md), apply them now so that the deployment you validate is the one you intend to run.

Next: [Validate your deployment](../validate/index.md).

<children></children>

---

# Install Coder via Docker

Source: https://coder.com/docs/install/server/docker

You can install and run Coder using the official Docker images published on
[GitHub Container Registry](https://github.com/coder/coder/pkgs/container/coder).

## Requirements

- Docker. See the
  [official installation documentation](https://docs.docker.com/install/).

- A Linux host.

- 2&nbsp;CPU cores and 4&nbsp;GB memory free on your machine.

> [!IMPORTANT]
> This guide is for **Linux** hosts only. The `getent` and `--group-add`
> Docker socket patterns used below are Linux-specific and do not translate
> cleanly to macOS Docker runtimes. For macOS, install Coder using the
> [standalone binary](../cli.md) instead.

<div class="tabs">

## Install Coder via `docker compose`

Coder publishes a
[docker compose example](../../../compose.yaml)
which includes a PostgreSQL container and volume.

1. Make sure you have [Docker Compose](https://docs.docker.com/compose/install/)
   installed.

1. Download the
   [`docker-compose.yaml`](../../../compose.yaml)
   file.

1. Update `group_add:` in `docker-compose.yaml` with the `gid` of `docker`
   group. You can get the `docker` group `gid` by running the below command:

   ```sh
   getent group docker | cut -d: -f3
   ```

1. Start Coder with `docker compose up`

1. Visit the web UI via the configured url.

1. Follow the on-screen instructions log in and create your first template and
   workspace

Coder configuration is defined via environment variables. Learn more about
Coder's [configuration options](../../admin/setup/index.md).

## Install Coder via `docker run`

### Built-in database (quick)

For proof-of-concept deployments, you can run a complete Coder instance with the
following command.

```sh
export CODER_DATA=$HOME/.config/coderv2-docker
export DOCKER_GROUP=$(getent group docker | cut -d: -f3)
mkdir -p $CODER_DATA
docker run --rm -it \
  -v $CODER_DATA:/home/coder/.config \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --group-add $DOCKER_GROUP \
  ghcr.io/coder/coder:latest
```

### External database (recommended)

For production deployments, we recommend using an external PostgreSQL database
(version 13 or higher). Set `CODER_ACCESS_URL` to the external URL that users
and workspaces will use to connect to Coder.

```sh
export DOCKER_GROUP=$(getent group docker | cut -d: -f3)
docker run --rm -it \
  -e CODER_ACCESS_URL="https://coder.example.com" \
  -e CODER_PG_CONNECTION_URL="postgresql://username:password@database/coder" \
  -v /var/run/docker.sock:/var/run/docker.sock \
  --group-add $DOCKER_GROUP \
  ghcr.io/coder/coder:latest
```

</div>

## Install the preview release

> [!TIP]
> We do not recommend using preview releases in production environments.

You can install and test a
[preview release of Coder](https://github.com/coder/coder/pkgs/container/coder-preview)
by using the `coder-preview:latest` image tag.
This image is automatically updated with the latest changes from the `main` branch.

Replace `ghcr.io/coder/coder:latest` in the `docker run` command in the
[steps above](#install-coder-via-docker-run) with `ghcr.io/coder/coder-preview:latest`.

## Troubleshooting

### Cannot connect to the Docker daemon

If you see an error like:

```txt
Error: Error pinging Docker server: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

Docker is not installed or not running on the host. Install Docker and start the
daemon before creating a workspace from a Docker-based template. Refer to the
[Troubleshooting section of the get started guide](../../get-started/index.md#cannot-connect-to-the-docker-daemon)
for platform-specific steps.

If Docker is installed and running but Coder still cannot connect, the daemon may expose its socket at a path other than `/var/run/docker.sock`.
This can happen on any operating system when Docker runs through a tool that uses a per-user socket, such as rootless Docker on Linux, or Colima, Podman, or Rancher Desktop on macOS.
Point Coder at the right socket with `DOCKER_HOST`.

Find the socket path first.
For example, run `colima status` for Colima, or `docker context inspect` to read the endpoint of the active Docker context.
Default socket paths vary by tool, so consult your tool's documentation and treat the following as examples only:

```sh
# rootless Docker (Linux)
export DOCKER_HOST="unix://${XDG_RUNTIME_DIR}/docker.sock"

# Colima (macOS)
export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
```

To persist the setting, add the `export` line to your shell's startup file, such as `~/.bashrc`, `~/.zshrc`, or `~/.config/fish/config.fish`.
Then restart the control plane.

### Docker-based workspace is stuck in "Connecting..."

Ensure you have an externally-reachable `CODER_ACCESS_URL` set. See
[troubleshooting templates](../../admin/templates/troubleshooting.md) for more
steps.

### Permission denied while trying to connect to the Docker daemon socket

See Docker's official documentation to
[Manage Docker as a non-root user](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user)

### I cannot add Docker templates

Coder runs as a non-root user, we use `--group-add` to ensure Coder has
permissions to manage Docker via `docker.sock`. If the host systems
`/var/run/docker.sock` is not group writable or does not belong to the `docker`
group, the above may not work as-is.

### I cannot add cloud-based templates

In order to use cloud-based templates (e.g. Kubernetes, AWS), you must have an
external URL that users and workspaces will use to connect to Coder. For
proof-of-concept deployments, you can use
[Coder's tunnel](../../admin/setup/index.md#tunnel). For production deployments, we
recommend setting an [access URL](../../admin/setup/index.md#access-url)

## Next steps

- [Create your first template](../../tutorials/template-from-scratch.md)
- [Control plane configuration](../../admin/setup/index.md)

---

# Install Coder on Kubernetes

Source: https://coder.com/docs/install/server/kubernetes

You can install Coder on Kubernetes (K8s) using Helm. We run on most Kubernetes
distributions, including [OpenShift](../openshift.md).

## Requirements

- Kubernetes cluster running K8s 1.19+
- [Helm](https://helm.sh/docs/intro/install/) 3.5+ installed on your local
  machine

## 1. Create a namespace

Create a namespace for the Coder control plane. In this tutorial, we'll call it
`coder`.

```sh
kubectl create namespace coder
```

## 2. Create a PostgreSQL instance

Coder does not manage a database server for you. This is required for storing
data about your Coder deployment and resources.

### Managed PostgreSQL (recommended)

If you're in a public cloud such as
[Google Cloud](https://cloud.google.com/sql/docs/postgres/),
[AWS](https://aws.amazon.com/rds/postgresql/),
[Azure](https://docs.microsoft.com/en-us/azure/postgresql/), or
[DigitalOcean](https://www.digitalocean.com/products/managed-databases-postgresql),
you can use the managed PostgreSQL offerings they provide. Make sure that the
PostgreSQL service is running and accessible from your cluster. It should be in
the same network, same project, etc.

### In-Cluster PostgreSQL (for proof of concepts)

You can install Postgres manually on your cluster using the
[Bitnami PostgreSQL Helm chart](https://github.com/bitnami/charts/tree/master/bitnami/postgresql#readme).
There are some [helpful guides](https://phoenixnap.com/kb/postgresql-kubernetes)
on the internet that explain sensible configurations for this chart. Example:

```console
# Install PostgreSQL
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install postgresql bitnami/postgresql \
    --namespace coder \
    --set image.repository=bitnamilegacy/postgresql \
    --set auth.username=coder \
    --set auth.password=coder \
    --set auth.database=coder \
    --set primary.persistence.size=10Gi
```

The cluster-internal DB URL for the above database is:

```sh
postgres://coder:coder@postgresql.coder.svc.cluster.local:5432/coder?sslmode=disable
```

You can optionally use the
[Postgres operator](https://github.com/zalando/postgres-operator) to manage
PostgreSQL deployments on your Kubernetes cluster.

## 3. Create the PostgreSQL secret

Create a secret with the PostgreSQL database URL string. In the case of the
self-managed PostgreSQL, the address will be:

```sh
kubectl create secret generic coder-db-url -n coder \
  --from-literal=url="postgres://coder:coder@postgresql.coder.svc.cluster.local:5432/coder?sslmode=disable"
```

## 4. Install Coder with Helm

```sh
helm repo add coder-v2 https://helm.coder.com/v2
```

Create a `values.yaml` with the configuration settings you'd like for your
deployment. For example:

```yaml
coder:
  # You can specify any environment variables you'd like to pass to Coder
  # here. Coder consumes environment variables listed in
  # `coder server --help`, and these environment variables are also passed
  # to the workspace provisioner (so you can consume them in your Terraform
  # templates for auth keys etc.).
  #
  # Please keep in mind that you should not set `CODER_HTTP_ADDRESS`,
  # `CODER_TLS_ENABLE`, `CODER_TLS_CERT_FILE` or `CODER_TLS_KEY_FILE` as
  # they are already set by the Helm chart and will cause conflicts.
  env:
    - name: CODER_PG_CONNECTION_URL
      valueFrom:
        secretKeyRef:
          # You'll need to create a secret called coder-db-url with your
          # Postgres connection URL like:
          # postgres://coder:password@postgres:5432/coder?sslmode=disable
          name: coder-db-url
          key: url
    # For production deployments, we recommend configuring your own GitHub
    # OAuth2 provider and disabling the default one.
    - name: CODER_OAUTH2_GITHUB_DEFAULT_PROVIDER_ENABLE
      value: "false"

    # (Optional) For production deployments the access URL should be set.
    # If you're just trying Coder, access the dashboard via the service IP.
    # - name: CODER_ACCESS_URL
    #   value: "https://coder.example.com"

  #tls:
  #  secretNames:
  #    - my-tls-secret-name
```

You can view our
[Helm README](../../../../helm/coder/README.md) for
details on the values that are available, or you can view the
[values.yaml](../../../../helm/coder/values.yaml)
file directly.

We support two release channels: mainline and stable - read the
[Releases](../../../reference/releases.md) page to learn more about which best suits your team.

- **Mainline** Coder release:

  - **Chart Registry**
    <!-- autoversion(mainline): "--version [version]" -->

    ```sh
    helm install coder coder-v2/coder \
        --namespace coder \
        --values values.yaml \
        --version 2.35.3
    ```

  - **OCI Registry**

    <!-- autoversion(mainline): "--version [version]" -->

    ```sh
    helm install coder oci://ghcr.io/coder/chart/coder \
        --namespace coder \
        --values values.yaml \
        --version 2.35.3
    ```

- **Stable** Coder release:

  - **Chart Registry**

    <!-- autoversion(stable): "--version [version]" -->

    ```sh
    helm install coder coder-v2/coder \
        --namespace coder \
        --values values.yaml \
        --version 2.33.6
    ```

  - **OCI Registry**

    <!-- autoversion(stable): "--version [version]" -->

    ```sh
    helm install coder oci://ghcr.io/coder/chart/coder \
        --namespace coder \
        --values values.yaml \
        --version 2.33.6
    ```

You can watch Coder start up by running `kubectl get pods -n coder`. Once Coder
has started, the `coder-*` pods should enter the `Running` state.

## 5. Log in to Coder 🎉

Use `kubectl get svc -n coder` to get the IP address of the LoadBalancer. Visit
this in the browser to set up your first account.

If you do not have a domain, you should set `CODER_ACCESS_URL` to this URL in
the Helm chart and upgrade Coder (see below). This allows workspaces to connect
to the proper Coder URL.

## Upgrade Coder via Helm

To upgrade Coder in the future or change values, you can run the following
command:

```sh
helm repo update
helm upgrade coder coder-v2/coder \
  --namespace coder \
  -f values.yaml
```

## Standalone AI gateway chart

Coder also publishes a chart, `oci://ghcr.io/coder/chart/coder-ai-gateway`, that runs [AI Gateway](../../../ai-coder/ai-gateway/index.md) as its own Deployment alongside the control plane.
Use it when you want to scale AI traffic independently of `coderd`.
For installation and configuration, refer to [Deploy AI Gateway as a standalone service](../../../ai-coder/ai-gateway/standalone.md) and the [AI Gateway Helm chart README](../../../../helm/ai-gateway/README.md).

## Coder Observability Chart

Use the [Observability Helm chart](https://github.com/coder/observability) for a
pre-built set of dashboards to monitor your control plane over time. It includes
Grafana, Prometheus, Loki, and Alert Manager out-of-the-box, and can be deployed
on your existing Grafana instance.

We recommend that all administrators deploying on Kubernetes set the
observability bundle up with the control plane from the start. For installation
instructions, visit the
[observability repository](https://github.com/coder/observability?tab=readme-ov-file#installation).

## Kubernetes Security Reference

Below are common requirements we see from our enterprise customers when
deploying an application in Kubernetes. This is intended to serve as a
reference, and not all security requirements may apply to your business.

1. **All container images must be sourced from an internal container registry.**

   - Control plane - To pull the control plane image from the appropriate
     registry,
     [update this Helm chart value](https://github.com/coder/coder/blob/f57ce97b5aadd825ddb9a9a129bb823a3725252b/helm/coder/values.yaml#L43-L50).
   - Workspaces - To pull the workspace image from your registry,
     [update the Terraform template code here](https://github.com/coder/coder/blob/f57ce97b5aadd825ddb9a9a129bb823a3725252b/examples/templates/kubernetes/main.tf#L271).
     This assumes your cluster nodes are authenticated to pull from the internal
     registry.

2. **All containers must run as non-root user**

   - Control plane - Our control plane pod
     [runs as non-root by default](https://github.com/coder/coder/blob/f57ce97b5aadd825ddb9a9a129bb823a3725252b/helm/coder/values.yaml#L124-L127).
   - Workspaces - Workspace pod UID is
     [set in the Terraform template here](https://github.com/coder/coder/blob/f57ce97b5aadd825ddb9a9a129bb823a3725252b/examples/templates/kubernetes/main.tf#L274-L276),
     and are not required to run as `root`.

3. **Containers cannot run privileged**

   - Coder's control plane does not run as privileged.
     [We disable](https://github.com/coder/coder/blob/f57ce97b5aadd825ddb9a9a129bb823a3725252b/helm/coder/values.yaml#L141)
     `allowPrivilegeEscalation`
     [by default](https://github.com/coder/coder/blob/f57ce97b5aadd825ddb9a9a129bb823a3725252b/helm/coder/values.yaml#L141).
   - Workspace pods do not require any elevated privileges, with the exception
     of our `envbox` workspace template (used for docker-in-docker workspaces,
     not required).

4. **Containers cannot mount host filesystems**

   - Both the control plane and workspace containers do not require any host
     filesystem mounts.

5. **Containers cannot attach to host network**

   - Both the control plane and workspaces use the Kubernetes networking layer
     by default, and do not require host network access.

6. **All Kubernetes objects must define resource requests/limits**

   - Both the control plane and workspaces set resource request/limits by
     default.

## Load balancing considerations

### AWS

If you are deploying Coder on AWS EKS and service is set to `LoadBalancer`, AWS
will default to the Classic load balancer. The load balancer external IP will be
stuck in a pending status unless sessionAffinity is set to None.

```yaml
coder:
  service:
    type: LoadBalancer
    sessionAffinity: None
```

AWS recommends a Network load balancer in lieu of the Classic load balancer. Use
the following `values.yaml` settings to request a Network load balancer:

```yaml
coder:
  service:
    externalTrafficPolicy: Local
    sessionAffinity: None
    annotations: { service.beta.kubernetes.io/aws-load-balancer-type: "nlb" }
```

By default, Coder will set the `externalTrafficPolicy` to `Cluster` which will
mask client IP addresses in the Audit log. To preserve the source IP, you can
either set this value to `Local`, or pass through the client IP via the
X-Forwarded-For header. To configure the latter, set the following environment
variables:

```yaml
coder:
  env:
    - name: CODER_PROXY_TRUSTED_HEADERS
      value: X-Forwarded-For
    - name: CODER_PROXY_TRUSTED_ORIGINS
      value: 10.0.0.1/8 # this will be the CIDR range of your Load Balancer IP address
```

### Azure

Certain enterprise environments require the
[Azure Application Gateway](https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-overview).
The Application Gateway supports:

- Websocket traffic (required for workspace connections)
- TLS termination

Follow our doc on
[how to deploy Coder on Azure with an Application Gateway](./kubernetes-azure-app-gateway.md)
for an example.

## Troubleshooting

You can view Coder's logs by getting the pod name from `kubectl get pods` and
then running `kubectl logs <pod name>`. You can also view these logs in your
Cloud's log management system if you are using managed Kubernetes.

### Kubernetes-based workspace is stuck in "Connecting..."

Ensure you have an externally-reachable `CODER_ACCESS_URL` set in your helm
chart. If you do not have a domain set up, this should be the IP address of
Coder's LoadBalancer (`kubectl get svc -n coder`).

See [troubleshooting templates](../../../admin/templates/troubleshooting.md) for more
steps.

## Next steps

- [Create your first template](../../../tutorials/template-from-scratch.md)
- [Control plane configuration](../../../admin/setup/index.md)

---

# Deploy Coder on Azure with an Application Gateway

Source: https://coder.com/docs/install/server/kubernetes/kubernetes-azure-app-gateway

In certain enterprise environments, the [Azure Application Gateway](https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-overview) is required.

These steps serve as a proof-of-concept example so that you can get Coder running with Kubernetes on Azure. Your deployment might require a separate Postgres server or signed certificates.

The Application Gateway supports:

- Websocket traffic (required for workspace connections)
- TLS termination

Refer to Microsoft's documentation on how to [enable application gateway ingress controller add-on for an existing AKS cluster with an existing application gateway](https://learn.microsoft.com/en-us/azure/application-gateway/tutorial-ingress-controller-add-on-existing).
The steps here follow the Microsoft tutorial for a Coder deployment.

## Deploy Coder on Azure with an Application Gateway

1. Create Azure resource group:

   ```sql
   az group create --name myResourceGroup --location eastus
   ```

1. Create AKS cluster:

   ```sql
   az aks create --name myCluster --resource-group myResourceGroup --network-plugin azure --enable-managed-identity --generate-ssh-keys
   ```

1. Create public IP:

   ```sql
   az network public-ip create --name myPublicIp --resource-group myResourceGroup --allocation-method Static --sku Standard
   ```

1. Create VNet and subnet:

   ```sql
   az network vnet create --name myVnet --resource-group myResourceGroup --address-prefix 10.0.0.0/16 --subnet-name mySubnet --subnet-prefix 10.0.0.0/24
   ```

1. Create Azure application gateway, attach VNet, subnet and public IP:

   ```sql
   az network application-gateway create --name myApplicationGateway --resource-group myResourceGroup --sku Standard_v2 --public-ip-address myPublicIp --vnet-name myVnet --subnet mySubnet --priority 100
   ```

1. Get app gateway ID:

   ```sql
   appgwId=$(az network application-gateway show --name myApplicationGateway --resource-group myResourceGroup -o tsv --query "id")
   ```

1. Enable app gateway ingress to AKS cluster:

   ```sql
   az aks enable-addons --name myCluster --resource-group myResourceGroup --addon ingress-appgw --appgw-id $appgwId
   ```

1. Get AKS node resource group:

   ```sql
   nodeResourceGroup=$(az aks show --name myCluster --resource-group myResourceGroup -o tsv --query "nodeResourceGroup")
   ```

1. Get AKS VNet name:

   ```sql
   aksVnetName=$(az network vnet list --resource-group $nodeResourceGroup -o tsv --query "[0].name")
   ```

1. Get AKS VNet ID:

   ```sql
   aksVnetId=$(az network vnet show --name $aksVnetName --resource-group $nodeResourceGroup -o tsv --query "id")
   ```

1. Peer VNet to AKS VNet:

   ```sql
   az network vnet peering create --name AppGWtoAKSVnetPeering --resource-group myResourceGroup --vnet-name myVnet --remote-vnet $aksVnetId --allow-vnet-access
   ```

1. Get app gateway VNet ID:

   ```sql
   appGWVnetId=$(az network vnet show --name myVnet --resource-group myResourceGroup -o tsv --query "id")
   ```

1. Peer AKS VNet to app gateway VNet:

   ```sql
   az network vnet peering create --name AKStoAppGWVnetPeering --resource-group $nodeResourceGroup --vnet-name $aksVnetName --remote-vnet $appGWVnetId --allow-vnet-access
   ```

1. Get AKS credentials:

   ```sql
   az aks get-credentials --name myCluster --resource-group myResourceGroup
   ```

1. Create Coder namespace:

   ```sh
   kubectl create ns coder
   ```

1. Deploy non-production PostgreSQL instance to AKS cluster:

   ```sh
   helm repo add bitnami https://charts.bitnami.com/bitnami
   helm install coder-db bitnami/postgresql \
   --set image.repository=bitnamilegacy/postgresql \
   --namespace coder \
   --set auth.username=coder \
   --set auth.password=coder \
   --set auth.database=coder \
   --set persistence.size=10Gi
   ```

1. Create the PostgreSQL secret:

   ```sh
   kubectl create secret generic coder-db-url -n coder --from-literal=url="postgres://coder:coder@coder-db-postgresql.coder.svc.cluster.local:5432/coder?sslmode=disable"
   ```

1. Get the application gateway's public IP address. Coder uses it as the access URL:

   ```sh
   az network public-ip show --name myPublicIp --resource-group myResourceGroup -o tsv --query "ipAddress"
   ```

1. Create a `values.yaml` file for the Coder Helm chart.
   Replace `<app-gateway-public-ip>` with the IP address from the previous step, or with a domain that resolves to it:

   ```yaml
   coder:
     env:
       - name: CODER_PG_CONNECTION_URL
         valueFrom:
           secretKeyRef:
             name: coder-db-url
             key: url
       - name: CODER_ACCESS_URL
         value: "http://<app-gateway-public-ip>"

     service:
       enable: true
       type: ClusterIP
       sessionAffinity: None
       externalTrafficPolicy: Cluster
       loadBalancerIP: ""
       annotations: {}
       httpNodePort: ""
       httpsNodePort: ""

     ingress:
       enable: true
       className: "azure-application-gateway"
       host: ""
       wildcardHost: ""
       annotations: {}
       tls:
         enable: false
         secretName: ""
         wildcardSecretName: ""
   ```

   The application gateway ingress controller that you enabled earlier watches for Ingress resources with the `azure-application-gateway` class and configures the gateway to route traffic to the Coder service.

1. Deploy Coder to AKS cluster:

   ```sh
   helm repo add coder-v2 https://helm.coder.com/v2
   helm install coder coder-v2/coder \
       --namespace coder \
       --values values.yaml \
       --version 2.25.2
   ```

1. Verify that the Ingress was assigned the application gateway's public IP address:

   ```sh
   kubectl get ingress -n coder
   ```

   After the `ADDRESS` column shows the IP address, go to your access URL in a browser to create the first Coder user.

1. When you no longer need the deployment, clean up Azure resources:

   ```sql
   az group delete --name myResourceGroup
   az group delete --name MC_myResourceGroup_myCluster_eastus
   ```

---

# Deploy Coder on Rancher

Source: https://coder.com/docs/install/server/rancher

You can deploy Coder on Rancher as a
[Workload](https://ranchermanager.docs.rancher.com/getting-started/quick-start-guides/deploy-workloads/workload-ingress).

## Requirements

- [SUSE Rancher Manager](https://ranchermanager.docs.rancher.com/getting-started/installation-and-upgrade/install-upgrade-on-a-kubernetes-cluster) running Kubernetes (K8s) 1.19+ with [SUSE Rancher Prime distribution](https://documentation.suse.com/cloudnative/rancher-manager/latest/en/integrations/kubernetes-distributions.html) (Rancher Manager 2.10+)
- Helm 3.5+ installed
- Workload Kubernetes cluster for Coder

## Overview

Installing Coder on Rancher involves four key steps:

1. Create a namespace for Coder
1. Set up PostgreSQL
1. Create a database connection secret
1. Install the Coder application via Rancher UI

## Create a namespace

Create a namespace for the Coder control plane. In this tutorial, we call it `coder`:

```sh
kubectl create namespace coder
```

## Set up PostgreSQL

Coder requires a PostgreSQL database to store deployment data.
We recommend that you use a managed PostgreSQL service, but you can use an in-cluster PostgreSQL service for non-production deployments:

<div class="tabs">

### Managed PostgreSQL (Recommended)

For production deployments, we recommend using a managed PostgreSQL service:

- [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/)
- [AWS RDS for PostgreSQL](https://aws.amazon.com/rds/postgresql/)
- [Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/)
- [DigitalOcean Managed PostgreSQL](https://www.digitalocean.com/products/managed-databases-postgresql)

Ensure that your PostgreSQL service:

- Is running and accessible from your cluster
- Is in the same network/project as your cluster
- Has proper credentials and a database created for Coder

### In-Cluster PostgreSQL (Development/PoC)

For proof-of-concept deployments, you can use Bitnami Helm chart to install PostgreSQL in your Kubernetes cluster:

```console
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install coder-db bitnami/postgresql \
    --set image.repository=bitnamilegacy/postgresql \
    --namespace coder \
    --set auth.username=coder \
    --set auth.password=coder \
    --set auth.database=coder \
    --set persistence.size=10Gi
```

After installation, the cluster-internal database URL will be:

```txt
postgres://coder:coder@coder-db-postgresql.coder.svc.cluster.local:5432/coder?sslmode=disable
```

For more advanced PostgreSQL management, consider using the
[Postgres operator](https://github.com/zalando/postgres-operator).

</div>

## Create the database connection secret

Create a Kubernetes secret with your PostgreSQL connection URL:

```sh
kubectl create secret generic coder-db-url -n coder \
  --from-literal=url="postgres://coder:coder@coder-db-postgresql.coder.svc.cluster.local:5432/coder?sslmode=disable"
```

> [!IMPORTANT]
> If you're using a managed PostgreSQL service, replace the connection URL with your specific database credentials.

## Install Coder through the Rancher UI

![Coder installed on Rancher](../../images/install/coder-rancher.png)

1. In the Rancher Manager console, select your target Kubernetes cluster for Coder.

1. Navigate to **Apps** > **Charts**

1. From the dropdown menu, select **Partners** and search for `Coder`

1. Select **Coder**, then **Install**

1. Select the `coder` namespace you created earlier and check **Customize Helm options before install**.

   Select **Next**

1. On the configuration screen, select **Edit YAML** and enter your Coder configuration settings:

   <details>
   <summary>Example values.yaml configuration</summary>

   ```yaml
   coder:
     # Environment variables for Coder
     env:
       - name: CODER_PG_CONNECTION_URL
         valueFrom:
           secretKeyRef:
             name: coder-db-url
             key: url

       # For production, uncomment and set your access URL
       # - name: CODER_ACCESS_URL
       #   value: "https://coder.example.com"

     # For TLS configuration (uncomment if needed)
     #tls:
     #  secretNames:
     #    - my-tls-secret-name
   ```

   For available configuration options, refer to the [Helm chart documentation](../../../helm)
   or [values.yaml file](../../../helm/coder/values.yaml).

   </details>

1. Select a Coder version:

   - **Mainline**: `2.37.1`
   - **Stable**: `2.36.5`

   Learn more about release channels in the [Releases documentation](../../reference/releases.md).

1. Select **Next** when your configuration is complete.

1. On the **Supply additional deployment options** screen:

   1. Accept the default settings
   1. Select **Install**

1. A Helm install output shell will be displayed and indicates the installation status.

## Manage your Rancher Coder deployment

To update or manage your Coder deployment later:

1. Navigate to **Apps** > **Installed Apps** in the Rancher UI.
1. Find and select Coder.
1. Use the options in the **⋮** menu for upgrade, rollback, or other operations.

## Next steps

- [Create your first template](../../tutorials/template-from-scratch.md)
- [Control plane configuration](../../admin/setup/index.md)

---

# OpenShift

Source: https://coder.com/docs/install/server/openshift

## Requirements

- OpenShift cluster running K8s 1.19+ (OpenShift 4.7+)
- Helm 3.5+ installed
- OpenShift CLI (`oc`) installed
- [Coder CLI](../cli.md) installed

## Install Coder with OpenShift

### 1. Authenticate to OpenShift and create a Coder project

Run the following command to login to your OpenShift cluster:

```sh
oc login --token=w4r...04s --server=<cluster-url>
```

Next, you will run the below command to create a project for Coder:

```sh
oc new-project coder
```

### 2. Configure SecurityContext values

Depending upon your configured Security Context Constraints (SCC), you'll need
to modify some or all of the following `securityContext` values from the default
values:

The below values are modified from Coder defaults and allow the Coder deployment
to run under the SCC `restricted-v2`.

> [!NOTE]
> `readOnlyRootFilesystem: true` is not technically required under
> `restricted-v2`, but is often mandated in OpenShift environments.

```yaml
coder:
  securityContext:
    runAsNonRoot: true # Unchanged from default
    runAsUser: <project-specific UID> # Default: 1000, replace this with the correct UID for your project.
    runAsGroup: <project-specific GID> # Default: 1000, replace this with the correct GID for your project.
    readOnlyRootFilesystem: true # Default: false, this is often required in OpenShift environments.
    seccompProfile: RuntimeDefault # Unchanged from default
```

- For `runAsUser` / `runAsGroup`, you can retrieve the correct values for
  project UID and project GID with the following command:

    ```console
    oc get project coder -o json | jq -r '.metadata.annotations'
    {
        "openshift.io/sa.scc.supplemental-groups": "1000680000/10000",
        "openshift.io/sa.scc.uid-range": "1000680000/10000"
    }
    ```

  Alternatively, you can set these values to `null` to allow OpenShift to
  automatically select the correct value for the project.

- For `readOnlyRootFilesystem`, consult the SCC under which Coder needs to run.
  In the below example, the `restricted-v2` SCC does not require a read-only
  root filesystem, while `restricted-custom` does:

  ```console
  oc get scc -o wide
  NAME               PRIV    CAPS                   SELINUX     RUNASUSER          FSGROUP     SUPGROUP    PRIORITY     READONLYROOTFS   VOLUMES
  restricted-custom   false   ["NET_BIND_SERVICE"]   MustRunAs   MustRunAsRange     MustRunAs   RunAsAny    <no value>   true             ["configMap","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
  restricted-v2       false   ["NET_BIND_SERVICE"]   MustRunAs   MustRunAsRange     MustRunAs   RunAsAny    <no value>   false            ["configMap","downwardAPI","emptyDir","ephemeral","persistentVolumeClaim","projected","secret"]
  ```

  If you are unsure, we recommend setting `readOnlyRootFilesystem` to `true` in
  an OpenShift environment.

- For `seccompProfile`: in some environments, you may need to set this to `null`
  to allow OpenShift to pick its preferred value.

### 3. Configure the Coder service, connection URLs, and cache values

To establish a connection to PostgreSQL, set the `CODER_PG_CONNECTION_URL`
value. [See our Helm documentation](./kubernetes/index.md) on configuring the
PostgreSQL connection URL as a secret. Additionally, if accessing Coder over a
hostname, set the `CODER_ACCESS_URL` value.

By default, Coder creates the cache directory in `/home/coder/.cache`. Given the
OpenShift-provided UID and `readOnlyRootFS` security context constraint, the
Coder container does not have permission to write to this directory.

To fix this, you can mount a temporary volume in the pod and set the
`CODER_CACHE_DIRECTORY` environment variable to that location. In the below
example, we mount this under `/tmp` and set the cache location to `/tmp/coder`.
This enables Coder to run with `readOnlyRootFilesystem: true`.

> [!NOTE]
> Depending on the number of templates and provisioners you use, you may
> need to increase the size of the volume, as the `coder` pod will be
> automatically restarted when this volume fills up.

Additionally, create the Coder service as a `ClusterIP`. In the next step, you
will create an OpenShift route that points to the service HTTP target port.

```yaml
coder:
  service:
    type: ClusterIP
  env:
    - name: CODER_CACHE_DIRECTORY
      value: /tmp/coder
    - name: CODER_PG_CONNECTION_URL
      valueFrom:
        secretKeyRef:
          key: url
          name: coder-db-url
    - name: CODER_ACCESS_URL
      value: "https://coder-example.apps.openshiftapps.com"
  securityContext:
    runAsNonRoot: true
    runAsUser: <project-specific UID>
    runAsGroup: <project-specific GID>
    readOnlyRootFilesystem: true
  volumes:
    - name: "cache"
      emptyDir:
        sizeLimit: 1Gi
  volumeMounts:
    - name: "cache"
      mountPath: "/tmp"
      readOnly: false
```

> [!NOTE]
> OpenShift provides a Developer Catalog offering you can use to install
> PostgreSQL into your cluster.

### 4. Create the OpenShift route

Below is the YAML spec for creating an OpenShift route that sends traffic to the
HTTP port of the Coder service:

```yaml
kind: Route
apiVersion: route.openshift.io/v1
metadata:
  namespace: coder
spec:
  host: https://coder-example.apps.openshiftapps.com
  to:
    kind: Service
    name: coder
  tls:
    # if set to edge, OpenShift will terminate TLS prior to the traffic reaching
    # the service.
    termination: edge
    # if set to Redirect, insecure client connections are redirected to the secure
    # port
    insecureEdgeTerminationPolicy: Redirect
  port:
    targetPort: http
```

Once complete, you can create this route in OpenShift via:

```console
oc apply -f route.yaml
```

### 5. Install Coder

You can now install Coder using the values you've set from the above steps. To
do so, run the series of `helm` commands below:

```sh
helm repo add coder-v2 https://helm.coder.com/v2
helm repo update
helm install coder coder-v2/coder \
  --namespace coder \
  --values values.yaml
```

> [!NOTE]
> If the Helm installation fails with a Kubernetes RBAC error, check the
> permissions of your OpenShift user using the `oc auth can-i` command.
>
> The below permissions are the minimum required:
>
> ```console
> oc auth can-i --list
> Resources                                          Non-Resource URLs   Resource Names    Verbs
> selfsubjectaccessreviews.authorization.k8s.io      []                  []                [create]
> selfsubjectrulesreviews.authorization.k8s.io       []                  []                [create]
> *                                                  []                  []                [get list watch create update patch delete deletecollection]
> *.apps                                             []                  []                [get list watch create update patch delete deletecollection]
> *.rbac.authorization.k8s.io                        []                  []                [get list watch create update patch delete deletecollection]
>                                                    [/.well-known/*]    []                [get]
>                                                    [/.well-known]      []                [get]
>                                                    [/api/*]            []                [get]
>                                                    [/api]              []                [get]
>                                                    [/apis/*]           []                [get]
>                                                    [/apis]             []                [get]
>                                                    [/healthz]          []                [get]
>                                                    [/healthz]          []                [get]
>                                                    [/livez]            []                [get]
>                                                    [/livez]            []                [get]
>                                                    [/openapi/*]        []                [get]
>                                                    [/openapi]          []                [get]
>                                                    [/readyz]           []                [get]
>                                                    [/readyz]           []                [get]
>                                                    [/version/]         []                [get]
>                                                    [/version/]         []                [get]
>                                                    [/version]          []                [get]
>                                                    [/version]          []                [get]
> securitycontextconstraints.security.openshift.io   []                  [restricted-v2]   [use]
> ```

### 6. Create an OpenShift-compatible image

While the deployment is spinning up, we will need to create some images that are
compatible with OpenShift. These images can then be run without modifying the
Security Context Constraints (SCCs) in OpenShift.

1. Determine the UID range for the project:

   ```console
   oc get project coder -o json | jq -r '.metadata.annotations'
   {
     "openshift.io/description": "",
     "openshift.io/display-name": "coder",
     "openshift.io/requester": "kube:admin",
     "openshift.io/sa.scc.mcs": "s0:c26,c15",
     "openshift.io/sa.scc.supplemental-groups": "1000680000/10000",
     "openshift.io/sa.scc.uid-range": "1000680000/10000"
   }
   ```

   Note the `uid-range` and `supplemental-groups`. In this case, the project
   `coder` has been allocated 10,000 UIDs and GIDs, both starting at
   `1000680000`.

   In this example, we will pick both UID and GID `1000680000`.

1. Create a `BuildConfig` referencing the source image you want to customize.
   This will automatically kick off a `Build` that will remain pending until
   step 3.

   > For more information, please consult the
   > [OpenShift Documentation](https://docs.openshift.com/container-platform/4.12/cicd/builds/understanding-buildconfigs.html).

   ```sh
   oc create -f - <<EOF
   kind: BuildConfig
   apiVersion: build.openshift.io/v1
   metadata:
     name: enterprise-base
     namespace: coder
   spec:
     output:
       to:
         kind: ImageStreamTag
         name: 'enterprise-base:latest'
     strategy:
       type: Docker
       dockerStrategy:
         imageOptimizationPolicy: SkipLayers
     source:
       type: Dockerfile
       dockerfile: |
         # Specify the source image.
         FROM docker.io/codercom/example-base:ubuntu

         # Switch to root
         USER root

         # As root:
         # 1) Remove the original coder user with UID 1000
         # 2) Add a coder group with an allowed UID
         # 3) Add a coder user as a member of the above group
         # 4) Fix ownership on the user's home directory
         RUN userdel coder && \
             groupadd coder -g 1000680000 && \
             useradd -l -u 1000680000 coder -g 1000680000 && \
             chown -R coder:coder /home/coder

         # Go back to the user 'coder'
         USER coder
     triggers:
       - type: ConfigChange
     runPolicy: Serial
   EOF
   ```

1. Create an `ImageStream` as a target for the previous step:

   ```sh
   oc create imagestream enterprise-base
   ```

   The `Build` created in the previous step should now begin. Once completed,
   you should see output similar to the following:

   ```console
   oc get imagestreamtag
   NAME                     IMAGE REFERENCE                                                                                                                                    UPDATED
   enterprise-base:latest   image-registry.openshift-image-registry.svc:5000/coder/enterprise-base@sha256:1dbbe4ee11be9218e1e4741264135a4f57501fe592d94d20db6bfe11692accd1   55 minutes ago
   ```

### 7. Create an OpenShift-compatible template

Start from the default "Kubernetes" template:

```sh
echo kubernetes | coderv2 templates init ./openshift-k8s
cd ./openshift-k8s
```

Edit `main.tf` and update the following fields of the Kubernetes pod resource:

- `spec.security_context`: remove this field.
- `spec.container.image`: update this field to the newly built image hosted on
  the OpenShift image registry from the previous step.
- `spec.container.security_context`: remove this field.

Finally, create the template:

```sh
coder template push kubernetes -d .
```

This template should be ready to use straight away.

## Next steps

- [Create your first template](../../tutorials/template-from-scratch.md)
- [Control plane configuration](../../admin/setup/index.md)

---

# Install Coder on RHEL-family Linux

Source: https://coder.com/docs/install/server/rpm

This guide is for a Coder deployment administrator who runs the Coder control plane on a single Red Hat Enterprise Linux host or another RHEL-family distribution.
Coder publishes an RPM with every release, and `systemd` manages the server like any other service.
For a multi-replica deployment, refer to [Kubernetes](./kubernetes/index.md) or [OpenShift](./openshift.md) instead.
To install the CLI on a client machine that connects to an existing deployment, refer to [Install the Coder CLI](../cli.md).

## Supported distributions

Coder builds one RPM per release and architecture.
The install script reads `/etc/os-release` and selects the RPM when `ID` or `ID_LIKE` names a Fedora-family or openSUSE-family distribution.

| Distribution             | Versions         | `ID`                                   |
|--------------------------|------------------|----------------------------------------|
| Red Hat Enterprise Linux | 8, 9, 10         | `rhel`                                 |
| Rocky Linux              | 8, 9, 10         | `rocky`                                |
| AlmaLinux                | 8, 9, 10         | `almalinux`                            |
| CentOS Stream            | 9, 10            | `centos`                               |
| Amazon Linux             | 2, 2023          | `amzn`                                 |
| Fedora                   | Current releases | `fedora`                               |
| openSUSE                 | Leap, Tumbleweed | `opensuse-leap`, `opensuse-tumbleweed` |

Every RHEL-family distribution in the table lists `fedora` in `ID_LIKE`, and both openSUSE variants list `opensuse`.
A derivative that isn't listed here takes the same path when its `ID_LIKE` includes `fedora`.
Each release publishes RPMs for `amd64`, `arm64`, and `armv7`.

## Requirements

- A host running one of the distributions above.
- 2&nbsp;CPU cores and 4&nbsp;GB of memory to evaluate Coder.
  For production sizing, refer to the [Coder Validated Architecture](../plan/sizing/index.md).
- `root` or `sudo` access.
- An external PostgreSQL database for anything beyond a proof of concept.
  Refer to [Using an external database](../../tutorials/external-database.md).

## Install the package

The install script detects the distribution and installs the matching RPM.
Install the package directly with `dnf` or `rpm` when the host can't run a piped shell script, or when you stage packages yourself.

<div class="tabs">

### Install script

```sh
curl -fsSL https://coder.com/install.sh | sh
```

The script installs the latest mainline release.
Pass `--stable` for the latest stable release, or `--version X.Y.Z` for a specific version.
Pass `--dry-run` to print the commands without running them.

### dnf

1. Download the RPM for your version and architecture from [GitHub releases](https://github.com/coder/coder/releases).
2. Install the package.

   ```sh
   sudo dnf install ./coder_<version>_linux_amd64.rpm
   ```

On hosts that use `yum`, run `sudo yum install` instead.

### rpm

Install or upgrade the package in place.
This is the command the install script runs.

```sh
sudo rpm -U coder_<version>_linux_amd64.rpm
```

</div>

The package installs the `coder` binary to `/usr/bin/coder`, the configuration file to `/etc/coder.d/coder.env`, and two `systemd` units: `coder.service` for the control plane and `coder-workspace-proxy.service` for an optional [workspace proxy](../../admin/networking/workspace-proxies.md).
It also creates the unprivileged `coder` user that the service runs as.

To stage the RPM on a host with no internet access, refer to [Air-gapped deployments](../prepare/airgap.md).

## Configure the server

`coder.service` doesn't start while `/etc/coder.d/coder.env` is empty.
Set your configuration before you start the service.

1. Open the configuration file.

   ```sh
   sudo vi /etc/coder.d/coder.env
   ```

2. Set `CODER_ACCESS_URL` to the external URL that users and workspaces connect to.
3. Set `CODER_PG_CONNECTION_URL` to your PostgreSQL connection string.
4. Save the file.

The file ships with the TLS and HTTP address variables commented in place.
For every server option, refer to the [configuration reference](../../admin/setup/configuration-reference.md).

## Start the service

1. Start Coder now and on every boot.

   ```sh
   sudo systemctl enable --now coder
   ```

2. Confirm that the service is running.

   ```console
   $ systemctl is-active coder
   active
   ```

3. Read the startup logs.

   ```sh
   journalctl -u coder.service -b
   ```

To test a configuration change without the service manager, run `coder server` in the foreground.

## SELinux and container runtimes in workspaces

SELinux affects workspaces that run their own container runtime.
If your templates run Docker or Podman inside a workspace on a RHEL-family node, refer to [Docker in workspaces](../../admin/templates/extending-templates/docker-in-workspaces.md) for the runtime requirements.

## Hardened base images

Coder publishes a container image built on Red Hat's UBI9-minimal base through [Iron Bank](https://ironbank.dso.mil/), the Department of Defense hardened container registry.
Choose that image when your compliance program requires an accredited base image.
The Iron Bank image is a container image, so deploy it with [Kubernetes](./kubernetes/index.md) or [OpenShift](./openshift.md) rather than through the RPM.

## Learn more

- [Validate your deployment](../validate/index.md)
- [Set up your control plane](../../admin/setup/index.md)
- [Create your first template](../../tutorials/template-from-scratch.md)
- [Upgrade Coder](../operate/upgrade.md)
- [Uninstall Coder](../operate/uninstall.md)

---

# Cloud platforms

Source: https://coder.com/docs/install/server/cloud

We provide install guides and example templates for deploying Coder to your
cloud of choice.

<div class="tabs">

## AWS

We publish Coder Community Edition on the AWS Marketplace. Follow the tutorial here:

- [Install Coder Community Edition from AWS Marketplace](./aws-marketplace.md)

Alternatively, install the [CLI binary](../../cli.md) on any Linux machine or
follow our [Kubernetes](../kubernetes/index.md) documentation to install Coder on an
existing Kubernetes cluster.

For EKS-specific installation guidance, see the [AWS section in Kubernetes installation docs](../kubernetes/index.md#aws).

## GCP

We publish a GCP Marketplace listing with Coder pre-installed. Follow the
tutorial here:

- [Install Coder on GCP Compute Engine](./compute-engine.md)

Alternatively, install the [CLI binary](../../cli.md) on any Linux machine or
follow our [Kubernetes](../kubernetes/index.md) documentation to install Coder on an
existing GKE cluster.

## Azure

Use the following guide to run Coder on an Azure VM:

- [Install Coder on an Azure VM](./azure-vm.md)

Alternatively, install the [CLI binary](../../cli.md) on any Linux machine or
follow our [Kubernetes](../kubernetes/index.md) documentation to install Coder on an
existing GKE cluster.

## Other

Is your cloud missing? Check [community](../community.md) install methods or
install the [standalone binary](../../cli.md).

</div>

---

# Amazon Web Services

Source: https://coder.com/docs/install/server/cloud/aws-marketplace

This guide is designed to get you up and running with a Coder proof-of-concept
on AWS EKS using a [Coder-provided CloudFormation Template](https://codermktplc-assets.s3.us-east-1.amazonaws.com/community-edition/eks-cluster.yaml).  The deployed AWS Coder Reference Architecture is below:
![Coder on AWS EKS](../../../images/platforms/aws/aws-coder-refarch-v1.png)

If you are familiar with EC2 however, you can use our
[install script](../../cli.md) to run Coder on any popular Linux distribution.

## Requirements

This guide assumes your AWS account has `AdministratorAccess` permissions given the number and types of AWS Services deployed.  After deployment of Coder into a AWS POC or Sandbox account, it is recommended that the permissions be scaled back to only what your deployment requires.

## Launch Coder Community Edition from the from AWS Marketplace

We publish an Ubuntu 22.04 Container Image with Coder pre-installed and a supporting AWS Marketplace Launch guide. Search for `Coder Community Edition` in the AWS Marketplace or
[launch directly from the Coder listing](https://aws.amazon.com/marketplace/pp/prodview-34vmflqoi3zo4).

![Coder on AWS Marketplace](../../../images/platforms/aws/marketplace-ce.png)

Use `View purchase options` to create a zero-cost subscription to Coder Community Edition and then use `Launch your software` to deploy to your current AWS Account.

![AWS Marketplace Subscription](../../../images/platforms/aws/marketplace-sub.png)

Select `EKS` for the Launch setup, choose the desired/lastest version to deploy, and then review the **Launch** instructions for more detail explanation of what will be deployed.  When you are ready to proceed, select the `CloudFormation Template` link under **Deployment templates**.

![AWS Marketplace Launch](../../../images/platforms/aws/marketplace-launch.png)

You will then be taken to the AWS Management Console, CloudFormation `Create stack` in the currently selected AWS Region.  Select `Next` to view the Coder Community Edition CloudFormation Stack parameters.

![AWS Marketplace Stack](../../../images/platforms/aws/marketplace-stack.png)

The default parameters will support POCs and small team deployments of Coder using `t3.large` (2&nbsp;cores and 8&nbsp;GB memory) Nodes.
While the deployment uses EKS Auto-mode and will scale using Karpenter, keep in mind this platforms is intended for proof-of-concept deployments.
You should adjust your infrastructure when preparing for production use.
See: [Scaling Coder](../../plan/index.md)

![AWS Marketplace Parameters](../../../images/platforms/aws/marketplace-parm.png)

Select `Next` and follow the prompts to submit the CloudFormation Stack.  Deployment of the Stack can take 10-20&nbsp;minutes, and will create EKS related sub-stacks and a CodeBuild pipeline that automates the initial Helm deployment of Coder and final AWS network services integration.  Once the Stack successfully creates, access the `Outputs` as shown below:

![AWS Marketplace Outputs](../../../images/platforms/aws/marketplace-output.png)

Look for the `CoderURL` output link, and use to navigate to your newly deployed instance of Coder Community Edition.

That's all! Use the UI to create your first user, template, and workspace. We recommend starting with a Kubernetes template since Coder Community Edition is deployed to EKS.

### Next steps

- [IDEs with Coder](../../../user-guides/workspace-access/index.md)
- [Writing custom templates for Coder](../../../admin/templates/index.md)
- [Configure the control plane](../../../admin/setup/index.md)
- [Use your own domain + TLS](../../../admin/setup/index.md#tls--reverse-proxy)

---

# Google Cloud Platform

Source: https://coder.com/docs/install/server/cloud/compute-engine

In this guide, you will learn how to deploy the Coder control plane instance and
your first template.

## Requirements

This guide assumes you have `roles/compute.instanceAdmin.v1` access to your
Google Cloud Platform project.

## Launch a Coder instance from the Google Cloud Marketplace

We publish an Ubuntu 22.04 VM image with Coder and Docker pre-installed.

Two SKU's are available via the Google Cloud Marketplace:

1. [License purchase via Google Cloud Marketplace](https://console.cloud.google.com/marketplace/product/coder-enterprise-market-public/coder-gcmp?inv=1&invt=Ab45rg&project=secret-beacon-468405-p5)
2. [A solution to deploy VM's on GCP (Bring Your Own License)](https://console.cloud.google.com/marketplace/product/workspan-public-422119/coder?inv=1&invt=Ab45rg&project=secret-beacon-468405-p5)

![Coder on GCP Marketplace](../../../images/platforms/gcp/marketplace.png)

Be sure to keep the default firewall options checked so you can connect over
HTTP, HTTPS, and SSH.

We recommend keeping the default instance type (`e2-standard-4`, 4&nbsp;cores and 16&nbsp;GB memory) if you plan on provisioning Docker containers as workspaces on this VM instance.
Keep in mind this platforms is intended for proof-of-concept deployments and you should adjust your infrastructure when preparing for production use.
See: [Scaling Coder](../../plan/index.md)

<video autoplay playsinline loop>
  <source src="../../../images/platforms/gcp/launch.mp4?raw=true" type="video/mp4">
Your browser does not support the video tag.
</video>

Be sure to add a keypair so that you can connect over SSH to further
[configure Coder](../../../admin/setup/index.md).

After launching the instance, wait 30&nbsp;seconds and navigate to the public IPv4 address.
You should be redirected to a public tunnel URL.

![Coder on GCP Marketplace start](../../../images/platforms/gcp/start.png)

That's all! Use the UI to create your first user, template, and workspace. We
recommend starting with a Docker template since the instance has Docker
pre-installed.

![Coder Workspace and IDE in GCP VM](../../../images/platforms/aws/workspace.png)

<a id="configuring-the-control-plane"></a>

## Configure the control plane

Coder is primarily configured by server-side flags and environment variables.
Given you created or added key-pairs when launching the instance, you can
[configure your Coder deployment](../../../admin/setup/index.md) by logging in via
SSH or using the console:

```sh
ssh ubuntu@<gcp-public-IPv4>
sudo vim /etc/coder.d/coder.env # edit config
sudo systemctl daemon-reload
sudo systemctl restart coder # restart Coder
```

## Give developers VM workspaces (optional)

Instead of running containers on the Coder instance, you can offer developers
full VM instances with the
[gcp-linux](../../../../examples/templates/gcp-linux/README.md)
template.

Before you can use this template, you must authorize Coder to create VM
instances in your GCP project. Follow the instructions in the
[gcp-linux template README](../../../../examples/templates/gcp-linux/README.md#authentication)
to set up authentication.

### Next Steps

- [Use your IDE with Coder](../../../user-guides/workspace-access/index.md)
- [Writing custom templates for Coder](../../../admin/templates/index.md)
- [Configure the control plane](../../../admin/setup/index.md)
- [Use your own domain + TLS](../../../admin/setup/index.md#tls--reverse-proxy)

---

# Microsoft Azure

Source: https://coder.com/docs/install/server/cloud/azure-vm

This guide shows you how to set up the Coder control plane on Azure which will
provision Azure-hosted Linux workspaces.

## Requirements

This guide assumes you have full administrator privileges on Azure.

## Create An Azure VM

From the Azure Portal, navigate to the Virtual Machines Dashboard.
Select **Create** to create a new Azure virtual machine.

<img src="../../../images/platforms/azure/azure1.jpg" alt="Azure VM creation page">

This will bring you to the `Create a virtual machine` page. Select the
subscription group of your choice, or create one if necessary.

Next, name the VM something relevant to this project using the naming convention
of your choice. Change the region to something more appropriate for your current
location. For this tutorial, we will use the base selection of the Ubuntu Gen2
Image and keep the rest of the base settings for this image the same.

<img src="../../../images/platforms/azure/azure2.png" alt="Azure VM instance details">

<img src="../../../images/platforms/azure/azure3.png" alt="Azure VM size selection">

Up next, under `Inbound port rules` modify the Select `inbound ports` to also
take in `HTTPS` and `HTTP`.

<img src="../../../images/platforms/azure/azure4.png" alt="Azure VM inbound port rules">

The set up for the image is complete at this stage.
Select **Review and Create**, review the information, and select **Create**.
A popup will appear asking you to download the key pair for the server.
Select **Download private key and create resource** and place it into a folder of your choice on your local system.

<img src="../../../images/platforms/azure/azure5.png" alt="Azure VM key pair generation">

Select **Return to create a virtual machine**.
Your VM will start up.

<img src="../../../images/platforms/azure/azure6.png" alt="Azure VM deployment complete">

Select **Go to resource** in the virtual machine and copy the public IP address.
You will need it to SSH into the virtual machine via your local machine.

Follow
[these instructions](https://learn.microsoft.com/en-us/azure/virtual-machines/linux-vm-connect?tabs=Linux)
to SSH into the virtual machine. Once on the VM, you can run and install Coder
using your method of choice. For the fastest install, we recommend running Coder
as a system service.

## Install Coder

For this instance, we will run Coder as a system service, however you can run
Coder a multitude of different ways. You can learn more about those
[here](https://coder.com/docs/install).

In the Azure VM instance, run the following command to install Coder

```sh
curl -fsSL https://coder.com/install.sh | sh
```

## Run Coder

Run the following command to start Coder as a system level service:

```sh
sudo systemctl enable --now coder
```

The following command will get you information about the Coder launch service

```sh
journalctl -u coder.service -b
```

This will return a series of logs related to running Coder as a system service.
Embedded in the logs is the Coder Access URL.

Copy the URL and run the following command to create the first user, either on
your local machine or in the instance terminal.

```sh
coder login <url***.try.coder.app>
```

Fill out the prompts. Be sure to save use email and password as these are your
admin username and password.

You can now access Coder on your local machine with the relevant
`***.try.coder.app` URL and logging in with the username and password.

<a id="creating-and-uploading-your-first-template"></a>

## Create and upload your first template

First, run `coder template init` to create your first template. You’ll be given
a list of possible templates to use. This tutorial will show you how to set up
your Coder instance to create a Linux based machine on Azure.

<img src="../../../images/platforms/azure/azure9.png" alt="Coder CLI template init">

Press `enter` to select `Develop in Linux on Azure` template. This will return
the following:

<img src="../../../images/platforms/azure/azure10.png" alt="Coder CLI template init">

To get started using the Azure template, install the Azure CLI by following the
instructions
[here](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt).
Run `az login` and follow the instructions to configure the Azure command line.

Coder is running as a system service, which creates the system user `coder` for
handling processes. The Coder user will require access to the Azure credentials
to initialize the template.

Run the following commands to copy the Azure credentials and give the `coder`
user access to them:

```sh
sudo cp -r ~/.azure /home/coder/.azure
sudo chown -R coder:coder /home/coder/.azure/
```

Navigate to the `./azure-linux` folder where you created your template and run
the following command to put the template on your Coder instance.

```sh
coder templates push
```

Congrats! You can now navigate to your Coder dashboard and use this Linux on
Azure template to create a new workspace!

---

# Community install methods

Source: https://coder.com/docs/install/server/community

The methods on this page are contributed and maintained by the Coder community, not by Coder.
They aren't covered by Coder support, and they're separate from the [Community](../../reference/glossary.md#community) license tier.
Use them when Coder doesn't package an install method for your platform, and check the linked project to see how current it is.
Contributions are welcome.

| Platform                                                                          | Documentation                                                                                |
|-----------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|
| Azure AKS                                                                         | [GitHub: coder-aks](https://github.com/ericpaulsen/coder-aks)                                |
| Terraform (GKE, AKS, LKE, DOKS, IBMCloud K8s, OVHCloud K8s, Scaleway K8s Kapsule) | [GitHub: coder-oss-terraform](https://github.com/ElliotG/coder-oss-tf)                       |
| Fly.io                                                                            | [Blog: Run Coder on Fly.io](https://coder.com/blog/remote-developer-environments-on-fly-io)  |
| Garden.io                                                                         | [GitHub: garden-coder-example](https://github.com/garden-io/garden-coder-example)            |
| Railway.com                                                                       | [Run Coder on Railway.com](https://railway.com/deploy/coder)                                 |
| Heroku                                                                            | [Docs: Deploy Coder on Heroku](https://github.com/coder/packages/blob/main/heroku/README.md) |
| Render                                                                            | [Docs: Deploy Coder on Render](https://github.com/coder/packages/blob/main/render/README.md) |
| Snapcraft                                                                         | [Get it from the Snap Store](https://snapcraft.io/coder)                                     |
| Easypanel                                                                         | [Deploy Coder on Easypanel](https://easypanel.io/templates/coder)                            |

---

# 4. Validate your deployment

Source: https://coder.com/docs/install/validate

Validation proves the deployment works and holds up under load.
Harden the deployment first, then measure it, so that the numbers reflect the configuration you will actually run.

## Harden first

- Confirm the deployment reports healthy in [Health check](../../admin/monitoring/health-check.md).
- Turn on the telemetry you need to interpret a load test, including [metrics](../../admin/monitoring/metrics.md) and [logs](../../admin/monitoring/logs.md).
- Apply the controls a security reviewer expects, such as [audit logs](../../admin/security/audit-logs.md) and [database encryption](../../admin/security/database-encryption.md).

## Then measure

- Run a load test that reflects your expected usage with [Scale testing](./scale-testing.md).
- Compare the results against the size target you chose in [Plan your deployment](../plan/index.md).
  A result that misses the target is a planning question, not a testing failure.

## Before you move on

You should have a template developers can build a workspace from, a successful workspace build by someone other than the person who installed Coder, and a load test result you're willing to show the team that owns the infrastructure.

Next: [Operate and maintain](../operate/index.md).

<children></children>

---

# Scale Testing

Source: https://coder.com/docs/install/validate/scale-testing

Scaling Coder involves planning and testing to ensure it can handle more load
without compromising service. This process encompasses infrastructure setup,
traffic projections, and aggressive testing to identify and mitigate potential
bottlenecks.

A dedicated Kubernetes cluster for Coder is recommended to configure, host, and
manage Coder workloads. Kubernetes provides container orchestration
capabilities, allowing Coder to efficiently deploy, scale, and manage workspaces
across a distributed infrastructure. This ensures high availability, fault
tolerance, and scalability for Coder deployments. Coder is deployed on this
cluster using the
[Helm chart](../server/kubernetes/index.md#4-install-coder-with-helm).

For more information about scaling, see our [Coder scaling best practices](../../tutorials/best-practices/scale-coder.md).

## Methodology

Our scale tests include the following stages:

1. Prepare environment: create expected users and provision workspaces.

1. SSH connections: establish user connections with agents, verifying their
   ability to echo back received content.

1. Web Terminal: verify the PTY connection used for communication with Web
   Terminal.

1. Workspace application traffic: assess the handling of user connections with
   specific workspace apps, confirming their capability to echo back received
   content effectively.

1. Dashboard evaluation: verify the responsiveness and stability of Coder
   dashboards under varying load conditions. This is achieved by simulating user
   interactions using instances of headless Chromium browsers.

1. Cleanup: delete workspaces and users created in step 1.

## Infrastructure and setup requirements

The scale tests runner can distribute the workload to overlap single scenarios
based on the workflow configuration:

|                      | T0 | T1 | T2 | T3 | T4 | T5 | T6 |
|----------------------|----|----|----|----|----|----|----|
| SSH connections      | X  | X  | X  | X  |    |    |    |
| Web Terminal (PTY)   |    | X  | X  | X  | X  |    |    |
| Workspace apps       |    |    | X  | X  | X  | X  |    |
| Dashboard (headless) |    |    |    | X  | X  | X  | X  |

This pattern closely reflects how our customers naturally use the system. SSH
connections are heavily utilized because they're the primary communication
channel for IDEs with VS Code and JetBrains plugins.

The basic setup of scale tests environment involves:

1. Scale tests runner (32&nbsp;vCPU, 128&nbsp;GB RAM)
1. Coder: 2 replicas (4&nbsp;vCPU, 16&nbsp;GB RAM)
1. Database: 1 instance (2&nbsp;vCPU, 32&nbsp;GB RAM)
1. Provisioner: 50 instances (0.5&nbsp;vCPU, 512&nbsp;MB RAM)

The test is deemed successful if:

- Users did not experience interruptions in their
workflows,
- `coderd` did not crash or require restarts, and
- No other internal errors were observed.

## Traffic Projections

In our scale tests, we simulate activity from 2000 users, 2000 workspaces, and 2000 agents, with two items of workspace agent metadata being sent every 10&nbsp;seconds.
Here are the resulting metrics:

Coder:

- Median CPU usage for `coderd`: 3&nbsp;vCPU, peaking at 3.7&nbsp;vCPU while all tests are running concurrently.
- Median API request rate: 350 RPS during dashboard tests, 250 RPS during Web
  Terminal and workspace apps tests.
- 2000 agent API connections with latency: p90 at 60&nbsp;ms, p95 at 220&nbsp;ms.
- on average 2400 Web Socket connections during dashboard tests.

Provisionerd:

- Median CPU usage is 0.35&nbsp;vCPU during workspace provisioning.

Database:

- Median CPU utilization is 80%, with a significant portion dedicated to writing
  workspace agent metadata.
- Memory utilization averages at 40%.
- `write_ops_count` between 6.7 and 8.4 operations per second.

## Available reference architectures

- [Up to 1,000 users](../plan/sizing/1k-users.md)

- [Up to 2,000 users](../plan/sizing/2k-users.md)

- [Up to 3,000 users](../plan/sizing/3k-users.md)
-
- [Up to 10,000 users](../plan/sizing/10k-users.md)

## Hardware recommendation

### Control plane: coderd

To ensure stability and reliability of the Coder control plane, it's essential
to focus on node sizing, resource limits, and the number of replicas. We
recommend referencing public cloud providers such as AWS, GCP, and Azure for
guidance on optimal configurations. A reasonable approach involves using scaling
formulas based on factors like CPU, memory, and the number of users.

While the minimum requirements specify 1&nbsp;CPU core and 2&nbsp;GB of memory per `coderd` replica, we recommend that you allocate additional resources depending on the workload size to ensure deployment stability.

#### CPU and memory usage

Enabling
[agent stats collection](../../reference/cli/server/index.md#--prometheus-collect-agent-stats)
(optional) may increase memory consumption.

Enabling direct connections between users and workspace agents (apps or SSH
traffic) can help prevent an increase in CPU usage. It is recommended to keep
[this option enabled](../../reference/cli/index.md#--disable-direct-connections)
unless there are compelling reasons to disable it.

Inactive users do not consume Coder resources.

#### Scaling formula

When determining scaling requirements, consider the following factors:

- `1 vCPU x 2 GB memory` for every 250 users: A reasonable formula to determine
  resource allocation based on the number of users and their expected usage
  patterns.
- API latency/response time: Monitor API latency and response times to ensure
  optimal performance under varying loads.
- Average number of HTTP requests: Track the average number of HTTP requests to
  gauge system usage and identify potential bottlenecks. The number of proxied
  connections: For a very high number of proxied connections, more memory is
  required.

#### HTTP API latency

For a reliable Coder deployment dealing with medium to high loads, it's important that API calls for workspace/template queries and workspace build operations respond within 300&nbsp;ms.
However, API template insights calls, which involve browsing workspace agent stats and user activity data, may require more time.
Moreover, Coder API exposes WebSocket long-lived connections for Web Terminal (bidirectional), and Workspace events/logs (unidirectional).

If the Coder deployment expects traffic from developers spread across the globe,
be aware that customer-facing latency might be higher because of the distance
between users and the load balancer. Fortunately, the latency can be improved
with a deployment of Coder
[workspace proxies](../../admin/networking/workspace-proxies.md).

#### Node Autoscaling

We recommend disabling the autoscaling for `coderd` nodes. Autoscaling can cause
interruptions for user connections, see
[Autoscaling](./scale-testing/utility.md#autoscaling) for more details.

### Control plane: Workspace Proxies

When scaling [workspace proxies](../../admin/networking/workspace-proxies.md), follow the
same guidelines as for `coderd` above:

- `1 vCPU x 2 GB memory` for every 250 users.
- Disable autoscaling.

### Control plane: provisionerd

Each external provisioner can run a single concurrent workspace build. For
example, running 10 provisioner containers will allow 10 users to start
workspaces at the same time.

By default, the control plane runs 3 built-in provisioner daemons, but the
_Premium_ Coder release allows for running external provisioners to separate the
load caused by workspace provisioning on the `coderd` nodes.

#### Scaling formula

When determining scaling requirements, consider the following factors:

- `1 vCPU x 1 GB memory x 2 concurrent workspace build`: A formula to determine
  resource allocation based on the number of concurrent workspace builds, and
  standard complexity of a Terraform template. _Rule of thumb_: the more
  provisioners are free/available, the more concurrent workspace builds can be
  performed.

#### Node Autoscaling

Autoscaling provisioners is not an easy problem to solve unless it can be
predicted when a number of concurrent workspace builds increases.

We recommend disabling autoscaling and adjusting the number of provisioners to
developer needs based on the workspace build queuing time.

### Data plane: Workspaces

To determine workspace resource limits and keep the best developer experience
for workspace users, administrators must be aware of a few assumptions.

- Workspace pods run on the same Kubernetes cluster, but possibly in a different
  namespace or on a separate set of nodes.
- Workspace limits (per workspace user):
  - Evaluate the workspace utilization pattern. For instance, web application
    development does not require high CPU capacity at all times, but will spike
    during builds or testing.
  - Evaluate minimal limits for single workspace.
    Include in the calculation requirements for Coder agent running in an idle workspace - 0.1&nbsp;vCPU and 256&nbsp;MB.
    For instance, developers can choose between 0.5-8&nbsp;vCPUs, and 1-16&nbsp;GB memory.

#### Scaling formula

When determining scaling requirements, consider the following factors:

- `1 vCPU x 2 GB memory x 1 workspace`: A formula to determine resource
  allocation based on the minimal requirements for an idle workspace with a
  running Coder agent and occasional CPU and memory bursts for building
  projects.

#### Node Autoscaling

Workspace nodes can be set to operate in autoscaling mode to mitigate the risk
of prolonged high resource utilization.

One approach is to scale up workspace nodes when total CPU usage or memory
consumption reaches 80%. Another option is to scale based on metrics such as the
number of workspaces or active users. It's important to note that as new users
onboard, the autoscaling configuration should account for ongoing workspaces.

Scaling down workspace nodes to zero is not recommended, as it will result in
longer wait times for workspace provisioning by users. However, this may be
necessary for workspaces with special resource requirements (e.g. GPUs) that
incur significant cost overheads.

---

# Scale tests and utilities

Source: https://coder.com/docs/install/validate/scale-testing/utility

We scale-test Coder with a built-in utility that can
be used in your environment for insights into how Coder scales with your
infrastructure. For scale-testing Kubernetes clusters we recommend that you install
and use the dedicated Coder template,
[scaletest-runner](../../../../scaletest/templates/scaletest-runner).

Learn more about [Coder’s architecture](../../plan/architecture.md) and our
[scale-testing methodology](../scale-testing.md).

For more information about scaling, see our [Coder scaling best practices](../../../tutorials/best-practices/scale-coder.md).

## Recent scale tests

The information in this doc is for reference purposes only, and is not intended
to be used as guidelines for infrastructure sizing.

Review the [Reference Architectures](../../plan/sizing/index.md#node-sizing) for
hardware sizing recommendations.

| Environment      | Coder CPU    | Coder RAM  | Coder Replicas | Database          | Users | Concurrent builds | Concurrent connections (Terminal/SSH) | Coder Version | Last tested  |
|------------------|--------------|------------|----------------|-------------------|-------|-------------------|---------------------------------------|---------------|--------------|
| Kubernetes (GKE) | 3&nbsp;cores | 12&nbsp;GB | 1              | db-f1-micro       | 200   | 3                 | 200 simulated                         | `v0.24.1`     | Jun 26, 2023 |
| Kubernetes (GKE) | 4&nbsp;cores | 8&nbsp;GB  | 1              | db-custom-1-3840  | 1500  | 20                | 1,500 simulated                       | `v0.24.1`     | Jun 27, 2023 |
| Kubernetes (GKE) | 2&nbsp;cores | 4&nbsp;GB  | 1              | db-custom-1-3840  | 500   | 20                | 500 simulated                         | `v0.27.2`     | Jul 27, 2023 |
| Kubernetes (GKE) | 2&nbsp;cores | 8&nbsp;GB  | 2              | db-custom-2-7680  | 1000  | 20                | 1000 simulated                        | `v2.2.1`      | Oct 9, 2023  |
| Kubernetes (GKE) | 4&nbsp;cores | 16&nbsp;GB | 2              | db-custom-8-30720 | 2000  | 50                | 2000 simulated                        | `v2.8.4`      | Feb 28, 2024 |
| Kubernetes (GKE) | 2&nbsp;cores | 4&nbsp;GB  | 2              | db-custom-2-7680  | 1000  | 50                | 1000 simulated                        | `v2.10.2`     | Apr 26, 2024 |

> [!NOTE]
> A simulated connection reads and writes random data at 40&nbsp;KB/s per connection.

## Scale testing utility

Since Coder's performance is highly dependent on the templates and workflows you
support, you may wish to use our internal scale testing utility against your own
environments.

> [!IMPORTANT]
> This utility is experimental.
>
> It is not subject to any compatibility guarantees and may cause interruptions
> for your users.
> To avoid potential outages and orphaned resources, we recommend that you run
> scale tests on a secondary "staging" environment or a dedicated
> Kubernetes playground cluster.
>
> Run it against a production environment at your own risk.

### Create workspaces

The following command will provision a number of Coder workspaces using the
specified template and extra parameters:

```sh
coder exp scaletest create-workspaces \
        --retry 5 \
        --count "${SCALETEST_PARAM_NUM_WORKSPACES}" \
        --template "${SCALETEST_PARAM_TEMPLATE}" \
        --concurrency "${SCALETEST_PARAM_CREATE_CONCURRENCY}" \
        --timeout 5h \
        --job-timeout 5h \
        --no-cleanup \
        --output json:"${SCALETEST_RESULTS_DIR}/create-workspaces.json"
```

The command does the following:

1. Create `${SCALETEST_PARAM_NUM_WORKSPACES}` workspaces concurrently
   (concurrency level: `${SCALETEST_PARAM_CREATE_CONCURRENCY}`) using the
   template `${SCALETEST_PARAM_TEMPLATE}`.
1. Leave workspaces running to use in next steps (`--no-cleanup` option).
1. Store provisioning results in JSON format.
1. If you don't want the creation process to be interrupted by any errors, use
   the `--retry 5` flag.

For more built-in `scaletest` options, use the `--help` flag:

```sh
coder exp scaletest create-workspaces --help
```

### Traffic Generation

Given an existing set of workspaces created previously with `create-workspaces`,
the following command will generate traffic similar to that of Coder's Web
Terminal against those workspaces.

```sh
# Produce load at about 1000MB/s (25MB/40ms).
coder exp scaletest workspace-traffic \
    --template "${SCALETEST_PARAM_GREEDY_AGENT_TEMPLATE}" \
    --bytes-per-tick $((1024 * 1024 * 25)) \
    --tick-interval 40ms \
    --timeout "$((delay))s" \
    --job-timeout "$((delay))s" \
    --scaletest-prometheus-address 0.0.0.0:21113 \
    --target-workspaces "0:100" \
    --trace=false \
  --output json:"${SCALETEST_RESULTS_DIR}/traffic-${type}-greedy-agent.json"
```

Traffic generation can be parametrized:

1. Send `bytes-per-tick` every `tick-interval`.
1. Enable tracing for performance debugging.
1. Target a range of workspaces with `--target-workspaces 0:100`.
1. For dashboard traffic: Target a range of users with `--target-users 0:100`.
1. Store provisioning results in JSON format.
1. Expose a dedicated Prometheus address (`--scaletest-prometheus-address`) for
   scaletest-specific metrics.

The `workspace-traffic` supports also other modes - SSH traffic, workspace app:

1. For SSH traffic: Use `--ssh` flag to generate SSH traffic instead of Web
   Terminal.
1. For workspace app traffic: Use `--app [wsdi|wsec|wsra]` flag to select app
   behavior.

   - `wsdi`: WebSocket discard
   - `wsec`: WebSocket echo
   - `wsra`: WebSocket read

### Cleanup

The scaletest utility will attempt to clean up all workspaces it creates. If you
wish to clean up all workspaces, you can run the following command:

```sh
coder exp scaletest cleanup \
    --cleanup-job-timeout 2h \
    --cleanup-timeout 15m
```

This will delete all workspaces and users with the prefix `scaletest-`.

## Scale testing template

Consider using a dedicated
[scaletest-runner](../../../../scaletest/templates/scaletest-runner)
template alongside the CLI utility for testing large-scale Kubernetes clusters.

The template deploys a main workspace with scripts used to orchestrate Coder,
creating workspaces, generating workspace traffic, or load-testing workspace
apps.

### Parameters

The _scaletest-runner_ offers the following configuration options:

- Workspace size selection: minimal/small/medium/large (_default_: minimal,
  which contains just enough resources for a Coder agent to run without
  additional workloads)
- Number of workspaces
- Wait duration between scenarios or staggered approach

The template exposes parameters to control the traffic dimensions for SSH
connections, workspace apps, and dashboard tests:

- Traffic duration of the load test scenario
- Traffic percentage of targeted workspaces
- Bytes per tick and tick interval
- _For workspace apps_: modes (echo, read random data, or write and discard)

Scale testing concurrency can be controlled with the following parameters:

- Enable parallel scenarios - interleave different traffic patterns (SSH,
  workspace apps, dashboard traffic, etc.)
- Workspace creation concurrency level (_default_: 10)
- Job concurrency level - generate workspace traffic using multiple jobs
  (_default_: 0)
- Cleanup concurrency level

### Kubernetes cluster

It is recommended to learn how to operate the _scaletest-runner_ before running
it against the staging cluster (or production at your own risk). Coder provides
different
[workspace configurations](../../../../scaletest/templates)
that operators can deploy depending on the traffic projections.

There are a few cluster options available:

| Workspace size | vCPU | Memory | Persisted storage | Details                                               |
|----------------|------|--------|-------------------|-------------------------------------------------------|
| minimal        | 1    | 2 Gi   | None              |                                                       |
| small          | 1    | 1 Gi   | None              |                                                       |
| medium         | 2    | 2 Gi   | None              | Medium-sized cluster offers the greedy agent variant. |
| large          | 4    | 4 Gi   | None              |                                                       |

Note: Review the selected cluster template and edit the node affinity to match
your setup.

#### Greedy agent

The greedy agent variant is a template modification that makes the Coder agent
transmit large metadata (size: 4K) while reporting stats. The transmission of
large chunks puts extra overhead on `coderd` instances and agents when handling
and storing the data.

Use this template variant to verify limits of the cluster performance.

### Observability

During scale tests, operators can monitor progress using a Grafana dashboard.
Coder offers a comprehensive overview
[dashboard](../../../../scaletest/scaletest_dashboard.json)
that can seamlessly integrate into the internal Grafana deployment.

This dashboard provides insights into various aspects, including:

- Utilization of resources within the Coder control plane (CPU, memory, pods)
- Database performance metrics (CPU, memory, I/O, connections, queries)
- `coderd` API performance (requests, latency, error rate)
- Resource consumption within Coder workspaces (CPU, memory, network usage)
- Internal metrics related to provisioner jobs

Note: Database metrics are disabled by default and can be enabled by setting the
environment variable `CODER_PROMETHEUS_COLLECT_DB_METRICS` to `true`.

It is highly recommended to deploy a solution for centralized log collection and
aggregation. The presence of error logs may indicate an underscaled deployment
of Coder, necessitating action from operators.

## Autoscaling

We generally do not recommend using an autoscaler that modifies the number of
`coderd` replicas. In particular, scale down events can cause interruptions for
a large number of users.

`coderd` is different from a simple request-response HTTP service in that it
services long-lived connections whenever it proxies HTTP applications like IDEs
or terminals that rely on websockets, or when it relays tunneled connections to
workspaces. Loss of a `coderd` replica will drop these long-lived connections
and interrupt users. For example, if you have 4 `coderd` replicas behind a load
balancer, and an autoscaler decides to reduce it to 3, roughly 25% of the
connections will drop. An even larger proportion of users could be affected if
they use applications that use more than one websocket.

The severity of the interruption varies by application. Coder's web terminal,
for example, will reconnect to the same session and continue. So, this should
not be interpreted as saying `coderd` replicas should never be taken down for
any reason.

We recommend you plan to run enough `coderd` replicas to comfortably meet your
weekly high-water-mark load, and monitor `coderd` peak CPU & memory utilization
over the long term, reevaluating periodically. When scaling down (or performing
upgrades), schedule these outside normal working hours to minimize user
interruptions.

### A note for Kubernetes users

When running on Kubernetes on cloud infrastructure (i.e. not bare metal), many
operators choose to employ a _cluster_ autoscaler that adds and removes
Kubernetes _nodes_ according to load. Coder can coexist with such cluster
autoscalers, but we recommend you take steps to prevent the autoscaler from
evicting `coderd` pods, as an eviction will cause the same interruptions as
described above. For example, if you are using the
[Kubernetes cluster autoscaler](https://kubernetes.io/docs/reference/labels-annotations-taints/#cluster-autoscaler-kubernetes-io-safe-to-evict),
you may wish to set `cluster-autoscaler.kubernetes.io/safe-to-evict: "false"` as
an annotation on the `coderd` deployment.

## Troubleshooting

If a load test fails or if you are experiencing performance issues during
day-to-day use, you can leverage Coder's
[Prometheus metrics](../../../admin/integrations/prometheus.md) to identify bottlenecks
during scale tests. Additionally, you can use your existing cloud monitoring
stack to measure load, view server logs, etc.

---

# Scale Coder

Source: https://coder.com/docs/tutorials/best-practices/scale-coder

This best practice guide helps you prepare a Coder deployment that you can
scale up to a high-scale deployment as use grows, and keep it operating smoothly with a
high number of active users and workspaces.

## Observability

Observability is one of the most important aspects to a scalable Coder deployment.
When you have visibility into performance and usage metrics, you can make informed
decisions about what changes you should make.

[Monitor your Coder deployment](../../admin/monitoring/index.md) with log output
and metrics to identify potential bottlenecks before they negatively affect the
end-user experience and measure the effects of modifications you make to your
deployment.

- Log output
  - Capture log output from from control plane instances and external provisioner daemons
  and store them in a searchable log store like Loki, CloudWatch logs, or other tools.
  - Retain logs for a minimum of thirty days, ideally ninety days.
  This allows you investigate when anomalous behaviors began.

- Metrics
  - Capture infrastructure metrics like CPU, memory, open files, and network I/O for all
  control plane, external provisioner daemon, workspace proxy, and PostgreSQL instances.
  - Capture control plane and external provisioner daemon metrics
  [via Prometheus](#how-to-capture-control-plane-metrics-with-prometheus).

Retain metric time series for at least six months. This allows you to see
performance trends relative to user growth.

For a more comprehensive overview, integrate metrics with an observability
dashboard like [Grafana](../../admin/monitoring/index.md).

### Observability key metrics

Configure alerting based on these metrics to ensure you surface problems before
they affect the end-user experience.

- CPU and Memory Utilization
  - Monitor the utilization as a fraction of the available resources on the instance.

     Utilization will vary with use throughout the course of a day, week, and longer timelines.
     Monitor trends and pay special attention to the daily and weekly peak utilization.
     Use long-term trends to plan infrastructure upgrades.

- Tail latency of Coder API requests
  - High tail latency can indicate the control plane or the PostgreSQL database is underprovisioned
  for the load.
  - Use the `coderd_api_request_latencies_seconds` metric.

- Tail latency of database queries
  - High tail latency can indicate the PostgreSQL database is low in resources.
  - Use the `coderd_db_query_latencies_seconds` metric.

### How to capture control plane metrics with Prometheus

Edit your Helm `values.yaml` to capture metrics from the control plane and external provisioner daemons with
[Prometheus](../../admin/integrations/prometheus.md):

1. Enable Prometheus metrics:

   ```yaml
   CODER_PROMETHEUS_ENABLE=true
   ```

1. Enable database metrics:

   ```yaml
   CODER_PROMETHEUS_COLLECT_DB_METRICS=true
   ```

1. For a high scale deployment, configure agent stats to avoid large cardinality or disable them:

   - Configure agent stats:

     ```yaml
     CODER_PROMETHEUS_AGGREGATE_AGENT_STATS_BY=agent_name
     ```

   - Disable agent stats:

     ```yaml
     CODER_PROMETHEUS_COLLECT_AGENT_STATS=false
     ```

## Control plane

### Locality

If increased availability of the Coder API is a concern, deploy at least three
control plane instances. Spread the instances across nodes with anti-affinity rules in
Kubernetes or in different availability zones of the same geographic region.

Do not deploy in different geographic regions.

Control plane instances need to be able to communicate with one another directly with low latency, under 10&nbsp;ms.
Note that this is for the availability of the Coder API.
Workspaces are not fault tolerant unless they are explicitly built that way at the template level.

Deploy control plane instances as geographically close to PostgreSQL as possible.
Low-latency communication (under 10&nbsp;ms) with Postgres is essential for control plane performance.

### Scaling

The control plane can be scaled both vertically for bigger instances and horizontally
for more instances.

Aim to keep the number of control plane instances relatively small, preferably
under ten instances, and opt for vertical scale over horizontal scale after
meeting availability requirements.

Coder's
[validated architectures](../../install/plan/sizing/index.md)
give specific sizing recommendations for various user scales. These are a useful
starting point, but very few deployments will remain stable at a predetermined
user level over the long term. We recommend monitoring and adjusting resources as needed.

We don't recommend that you autoscale the control plane instances. Instead, scale the
deployment for peak weekly usage.

Although the control plane persists no internal state, it operates as a proxy for end
users to their workspaces in two capacities:

1. As an HTTP proxy when they access workspace applications in their browser via
   the Coder Dashboard.

1. As a DERP proxy when establishing tunneled connections with CLI tools like
   `coder ssh`, `coder port-forward`, and others, and with desktop IDEs.

Stopping a control plane instance will (momentarily) disconnect any users
currently connecting through that instance. Adding a new instance is not
disruptive, but you should remove instances and perform upgrades during a
maintenance window to minimize disruption.

## Provisioner daemons

### Locality

We recommend that you run one or more
[provisioner daemon deployments external to the control plane](../../install/operate/provisioners/index.md)
and disable provisioner daemons within your control plane.
This allows you to scale them independently of the control plane:

```yaml
CODER_PROVISIONER_DAEMONS=0
```

We recommend deploying provisioner daemons within the same cluster as the
workspaces they will provision or are hosted in.

- This gives them a low-latency connection to the APIs they will use to
  provision workspaces and can speed builds.

- It allows provisioner daemons to use in-cluster mechanisms (for example
  Kubernetes service account tokens, AWS IAM Roles, and others) to authenticate with
  the infrastructure APIs.

- If you deploy workspaces in multiple clusters, run multiple provisioner daemon
  deployments and use template tags to select the correct set of provisioner
  daemons.

- Provisioner daemons need to be able to connect to the control plane, but this does not need
  to be a low-latency connection.

Provisioner daemons make no direct connections to the PostgreSQL database, so
there's no need for locality to the Postgres database.

### Scaling

Each provisioner daemon instance can handle a single workspace build job at a
time. Therefore, the maximum number of simultaneous builds your Coder deployment
can handle is equal to the number of provisioner daemon instances within a tagged
deployment.

If users experience unacceptably long queues for workspace builds to start,
consider increasing the number of provisioner daemon instances in the affected
cluster.

You might need to automatically scale the number of provisioner daemon instances
throughout the day to meet demand.

If you stop instances with `SIGHUP`, they will complete their current build job
and exit. `SIGINT` will cancel the current job, which will result in a failed build.
Ensure your autoscaler waits long enough for your build jobs to complete before
it kills the provisioner daemon process.

If you deploy in Kubernetes, we recommend a single provisioner daemon per pod.
On a virtual machine (VM), you can deploy multiple provisioner daemons, ensuring
each has a unique `CODER_CACHE_DIRECTORY` value.

Coder's
[validated architectures](../../install/plan/sizing/index.md)
give specific sizing recommendations for various user scales. Since the
complexity of builds varies significantly depending on the workspace template,
consider this a starting point. Monitor queue times and build times and adjust
the number and size of your provisioner daemon instances.

## PostgreSQL

PostgreSQL is the primary persistence layer for all of Coder's deployment data.
We also use `LISTEN` and `NOTIFY` to coordinate between different instances of
the control plane.

### Locality

Control plane instances must have low-latency connections (under 10&nbsp;ms) to PostgreSQL.
If you use multiple PostgreSQL replicas in a clustered config, these must also be low-latency with respect to one another.

### Scaling

Prefer scaling PostgreSQL vertically rather than horizontally for best
performance. Coder's
[validated architectures](../../install/plan/sizing/index.md)
give specific sizing recommendations for various user scales.

### Connection pool tuning

The control plane maintains a pool of connections to PostgreSQL. You can tune the
pool size with the following settings:

> [!NOTE]
> When adjusting these settings, please ensure that your PostgreSQL Server has `max_connections`
> set appropriately to accommodate all control plane replicas multiplied by the
> maximum number of open connections. We recommend configuring an additional 20%
> of connections to account for churn and other clients.
>
> Also note that increasing `max_connections` will result in potentially higher
> CPU and RAM usage, so you'll need to monitor accordingly.

- `--postgres-conn-max-open` (env: `CODER_PG_CONN_MAX_OPEN`): Maximum number of open
  connections. Default: 10.
- `--postgres-conn-max-idle` (env: `CODER_PG_CONN_MAX_IDLE`): Maximum number of idle
  connections kept in the pool. Default: "auto", which uses max open / 3.

When a connection is returned to the pool and the idle pool is already full, the
connection is closed immediately. This can cause connection establishment
overhead (churn) when load fluctuates. Monitor these metrics to understand your
connection pool behavior:

- **Capacity**: `go_sql_max_open_connections - go_sql_in_use_connections` shows
  how many connections are available for new requests. If this is 0, control
  plane performance will start to degrade. This just provides a point-in-time view
  of the connections, however.

  For a more systematic view, consider running
  `sum by (pod) (increase(go_sql_wait_duration_seconds_total[1m]))` to see how long
  each Coder replica spent waiting on the connection pool (i.e. no free connections);
  `sum by (pod) (increase(go_sql_wait_count_total[$__interval]))` shows how many
  connections were waited for.

  If either of these values seem unacceptably high, try tuning the above settings.
- **Churn**: `sum(rate(go_sql_max_idle_closed_total[$__rate_interval]))` shows
  how many connections are being closed because the idle pool is full.

If you see high churn, consider increasing `--pg-conn-max-idle` to keep more
connections ready for reuse. If you see capacity consistently near zero,
consider increasing `--pg-conn-max-open`.

## Workspace proxies

Workspace proxies proxy HTTP traffic from end users to workspaces for Coder apps
defined in the templates, and HTTP ports opened by the workspace. By default
they also include a DERP Proxy.

### Locality

We recommend each geographic cluster of workspaces have an associated deployment
of workspace proxies. This ensures that users always have a near-optimal proxy
path.

### Scaling

Workspace proxy load is determined by the amount of traffic they proxy.

Monitor CPU, memory, and network I/O utilization to decide when to resize
the number of proxy instances.

Scale for peak demand and scale down or upgrade during a maintenance window.

We do not recommend autoscaling the workspace proxies because many applications
use long-lived connections such as websockets, which would be disrupted by
stopping the proxy.

## Workspaces

Workspaces represent the vast majority of resources in most Coder deployments.
Because they are defined by templates, there is no one-size-fits-all advice for
scaling workspaces.

### Hard and soft cluster limits

All Infrastructure as a Service (IaaS) clusters have limits to what can be
simultaneously provisioned. These could be hard limits, based on the physical
size of the cluster, especially in the case of a private cloud, or soft limits,
based on configured limits in your public cloud account.

It is important to be aware of these limits and monitor Coder workspace resource
utilization against the limits, so that a new influx of users don't encounter
failed builds. Monitoring these is outside the scope of Coder, but we recommend
that you set up dashboards and alerts for each kind of limited resource.

As you approach soft limits, you can request limit increases to keep growing.

As you approach hard limits, consider deploying to additional cluster(s).

### Workspaces per node

Many development workloads are "spiky" in their CPU and memory requirements, for
example, they peak during build/test and then lower while editing code.
This leads to an opportunity to efficiently use compute resources by packing multiple
workspaces onto a single node. This can lead to better experience (more CPU and
memory available during brief bursts) and lower cost.

There are a number of things you should consider before you decide how many
workspaces you should allow per node:

- "Noisy neighbor" issues: Users share the node's CPU and memory resources and might
be susceptible to a user or process consuming shared resources.

- If the shared nodes are a provisioned resource, for example, Kubernetes nodes
  running on VMs in a public cloud, then it can sometimes be a challenge to
  effectively autoscale down.

  - For example, if half the workspaces are stopped overnight, and there are ten
    workspaces per node, it's unlikely that all ten workspaces on the node are
    among the stopped ones.

  - You can mitigate this by lowering the number of workspaces per node, or
    using autostop policies to stop more workspaces during off-peak hours.

- If you do overprovision workspaces onto nodes, keep them in a separate node
  pool and schedule the control plane, PostgreSQL, and workspace proxy
  components on a different node pool to avoid resource spikes
  affecting them.

Coder customers have had success with both:

- One workspace per AWS VM
- Lots of workspaces on Kubernetes nodes for efficiency

### Cost control

- Use quotas to discourage users from creating many workspaces they don't need
  simultaneously.

- Label workspace cloud resources by user, team, organization, or your own
  labelling conventions to track usage at different granularities.

- Use autostop requirements to bring off-peak utilization down.

## Networking

Set up your network so that most users can get direct, peer-to-peer connections
to their workspaces. This drastically reduces the load on the control plane and
workspace proxy instances.

## Next steps

- [Scale Tests and Utilities](../../install/validate/scale-testing/utility.md)
- [Scale Testing](../../install/validate/scale-testing.md)

---

# 5. Operate and maintain

Source: https://coder.com/docs/install/operate

Day-two operations cover the work that keeps a deployment healthy after it's installed: upgrades, provisioning capacity, and eventual removal.

## What this phase covers

- [External provisioners](./provisioners/index.md) to isolate workspace builds from the control plane and to add build capacity.
- [Upgrading](./upgrade.md), including [upgrade best practices](./upgrade/best-practices.md) and the Extended Support Release upgrade paths.
- [Uninstall](./uninstall.md), for decommissioning a deployment and removing the resources it created.

## What lives elsewhere

Ongoing administration isn't part of this section.
Authentication, user and group management, templates, networking, monitoring, and security are covered in [Administration](../../admin/index.md).
Revisit [Plan your deployment](../plan/index.md) when your user count outgrows the size you originally chose, and [Validate your deployment](../validate/index.md) after any change large enough to alter the load profile.

<children></children>

---

# External provisioners

Source: https://coder.com/docs/install/operate/provisioners

By default, the control plane runs
[built-in provisioner daemons](../../../reference/cli/server/index.md#--provisioner-daemons),
which execute `terraform` during workspace and template builds. However, there
are often benefits to running external provisioner daemons:

- **Secure build environments:** Run build jobs in isolated containers,
  preventing malicious templates from gaining sh access to the Coder host.

- **Isolate APIs:** Deploy provisioners in isolated environments (on-prem, AWS,
  Azure) instead of exposing APIs (Docker, Kubernetes, VMware) to the control
  plane. See
  [Provider Authentication](../../../admin/templates/extending-templates/provider-authentication.md)
  for more details.

- **Isolate secrets**: Keep Coder unaware of cloud secrets, manage/rotate
  secrets on provisioner servers.

- **Reduce control plane load**: External provisioners reduce load and build
  queue times from the control plane. See
  [Scaling Coder](../../validate/scale-testing.md) for more
  details.

Each provisioner runs a single
[concurrent workspace build](../../validate/scale-testing.md#control-plane-provisionerd).
For example, running 30 provisioner containers will allow 30 users to start
workspaces at the same time.

Provisioners are started with the
[`coder provisioner start`](../../../reference/cli/provisioner/start.md) command in
the [full Coder binary](https://github.com/coder/coder/releases). Keep reading
to learn how to start provisioners via Docker, Kubernetes, Systemd, etc.

You can use the dashboard, CLI, or API to [manage provisioners](./manage-provisioner-jobs.md).

## Authentication

The provisioner daemon must authenticate with your Coder deployment.

<div class="tabs">

## Scoped Key (Recommended)

We recommend creating finely-scoped keys for provisioners. Keys are scoped to an
organization, and optionally to a specific set of tags.

1. Use `coder provisioner` to create the key:

   - To create a key for an organization that will match untagged jobs:

     ```sh
     coder provisioner keys create my-key \
       --org default

     Successfully created provisioner key   my-key! Save this authentication token, it   will not be shown    again.

     <key omitted>
     ```

   - To restrict the provisioner to jobs with specific tags:

     ```sh
     coder provisioner keys create kubernetes-key \
       --org default \
       --tag environment=kubernetes

     Successfully created provisioner key kubernetes-key! Save this    authentication token, it will not be    shown again.

     <key omitted>
     ```

1. Start the provisioner with the specified key:

   ```sh
   export CODER_URL=https://<your-coder-url>
   export CODER_PROVISIONER_DAEMON_KEY=<key>
   coder provisioner start
   ```

Keep reading to see instructions for running provisioners on
Kubernetes/Docker/etc.

## User Tokens

A user account with the role `Template Admin` or `Owner` can start provisioners
using their user account. This may be beneficial if you are running provisioners
via [automation](../../../reference/index.md).

```sh
coder login https://<your-coder-url>
coder provisioner start
```

To start a provisioner with specific tags:

```sh
coder login https://<your-coder-url>
coder provisioner start \
  --tag environment=kubernetes
```

Note: Any user can start [user-scoped provisioners](#user-scoped-provisioners),
but this will also require a template on your deployment with the corresponding
tags.

## Global PSK (Not Recommended)

We do not recommend using global PSK.

Global pre-shared keys (PSK) make it difficult to rotate keys or isolate provisioners.

A deployment-wide PSK can be used to authenticate any provisioner. To use a
global PSK, set a
[provisioner daemon pre-shared key (PSK)](../../../reference/cli/server/index.md#--provisioner-daemon-psk)
on the control plane.

Next, start the provisioner:

```sh
coder provisioner start --psk <your-psk>
```

</div>

## Provisioner Tags

You can use **provisioner tags** to control which provisioners can pick up build
jobs from templates (and corresponding workspaces) with matching explicit tags.

Provisioners have two implicit tags: `scope` and `owner`. Coder sets these tags
automatically.

- Organization-scoped provisioners always have the implicit tags
  `scope=organization owner=""`
- User-scoped provisioners always have the implicit tags
  `scope=user owner=<uuid>`

For example:

```sh
# Start a provisioner with the explicit tags
# environment=on_prem and datacenter=chicago
coder provisioner start \
  --tag environment=on_prem \
  --tag datacenter=chicago

# In another terminal, create/push
# a template that requires the explicit
# tag environment=on_prem
coder templates push on-prem \
  --provisioner-tag environment=on_prem

# Or, match the provisioner's explicit tags exactly
coder templates push on-prem-chicago \
  --provisioner-tag environment=on_prem \
  --provisioner-tag datacenter=chicago
```

This can also be done in the UI when building a template:

![template tags](../../../images/admin/provisioner-tags.png)

Alternatively, a template can target a provisioner via
[workspace tags](../../../../examples/workspace-tags)
inside the Terraform. See the
[workspace tags documentation](../../../admin/templates/extending-templates/workspace-tags.md)
for more information.

> [!NOTE]
> Workspace tags defined with the `coder_workspace_tags` data source
> template **do not** automatically apply to the template import job! You may
> need to specify the desired tags when importing the template.

A provisioner can run a given build job if one of the below is true:

1. A job with no explicit tags can only be run on a provisioner with no explicit
   tags. This way you can introduce tagging into your deployment without
   disrupting existing provisioners and jobs.
1. If a job has any explicit tags, it can only run on a provisioner with those
   explicit tags (the provisioner could have additional tags).

The external provisioner in the above example can run build jobs in the same
organization with tags:

- `environment=on_prem`
- `datacenter=chicago`
- `environment=on_prem datacenter=chicago`

However, it will not pick up any build jobs that do not have either of the
`environment` or `datacenter` tags set. It will also not pick up any build jobs
from templates with the tag `scope=user` set, or build jobs from templates in
different organizations.

> [!NOTE]
> If you only run tagged provisioners, you will need to specify a set of
> tags that matches at least one provisioner for _all_ template import jobs and
> workspace build jobs.
>
> You may wish to run at least one additional provisioner with no additional
> tags so that provisioner jobs with no additional tags defined will be picked
> up instead of potentially remaining in the Pending state indefinitely.

This is illustrated in the below table:

| Provisioner Tags                                                  | Job Tags                                                         | Same Org | Can Run Job? |
|-------------------------------------------------------------------|------------------------------------------------------------------|----------|--------------|
| scope=organization owner=                                         | scope=organization owner=                                        | ✅        | ✅            |
| scope=organization owner= environment=on-prem                     | scope=organization owner= environment=on-prem                    | ✅        | ✅            |
| scope=organization owner= environment=on-prem datacenter=chicago  | scope=organization owner= environment=on-prem                    | ✅        | ✅            |
| scope=organization owner= environment=on-prem datacenter=chicago  | scope=organization owner= environment=on-prem datacenter=chicago | ✅        | ✅            |
| scope=user owner=aaa                                              | scope=user owner=aaa                                             | ✅        | ✅            |
| scope=user owner=aaa environment=on-prem                          | scope=user owner=aaa                                             | ✅        | ✅            |
| scope=user owner=aaa environment=on-prem                          | scope=user owner=aaa environment=on-prem                         | ✅        | ✅            |
| scope=user owner=aaa environment=on-prem datacenter=chicago       | scope=user owner=aaa environment=on-prem                         | ✅        | ✅            |
| scope=user owner=aaa environment=on-prem datacenter=chicago       | scope=user owner=aaa environment=on-prem datacenter=chicago      | ✅        | ✅            |
| scope=organization owner=                                         | scope=organization owner= environment=on-prem                    | ✅        | ❌            |
| scope=organization owner= environment=on-prem                     | scope=organization owner=                                        | ✅        | ❌            |
| scope=organization owner= environment=on-prem                     | scope=organization owner= environment=on-prem datacenter=chicago | ✅        | ❌            |
| scope=organization owner= environment=on-prem datacenter=new_york | scope=organization owner= environment=on-prem datacenter=chicago | ✅        | ❌            |
| scope=user owner=aaa                                              | scope=organization owner=                                        | ✅        | ❌            |
| scope=user owner=aaa                                              | scope=user owner=bbb                                             | ✅        | ❌            |
| scope=organization owner=                                         | scope=user owner=aaa                                             | ✅        | ❌            |
| scope=organization owner=                                         | scope=user owner=aaa environment=on-prem                         | ✅        | ❌            |
| scope=user owner=aaa                                              | scope=user owner=aaa environment=on-prem                         | ✅        | ❌            |
| scope=user owner=aaa environment=on-prem                          | scope=user owner=aaa environment=on-prem datacenter=chicago      | ✅        | ❌            |
| scope=user owner=aaa environment=on-prem datacenter=chicago       | scope=user owner=aaa environment=on-prem datacenter=new_york     | ✅        | ❌            |
| scope=organization owner= environment=on-prem                     | scope=organization owner= environment=on-prem                    | ❌        | ❌            |

> [!TIP]
> To generate this table, run the following command and
> copy the output:
>
> ```go
> go test -v -count=1 ./coderd/provisionerdserver/ -test.run='^TestAcquirer_MatchTags/GenTable$'
> ```

## Types of provisioners

Provisioners can broadly be categorized by scope: `organization` or `user`. The
scope of a provisioner can be specified with
[`-tag=scope=<scope>`](../../../reference/cli/provisioner/start.md#-t---tag) when
starting the provisioner daemon. Only users with at least the
[Template Admin](../../../admin/users/index.md#roles) role or higher may create
organization-scoped provisioner daemons.

There are two exceptions:

- [Built-in provisioners](../../../reference/cli/server/index.md#--provisioner-daemons) are
  always organization-scoped.
- External provisioners started using a
  [pre-shared key (PSK)](../../../reference/cli/provisioner/start.md#--psk) are always
  organization-scoped.

### Organization-Scoped Provisioners

**Organization-scoped Provisioners** can pick up build jobs created by any user.
These provisioners always have the implicit tags `scope=organization owner=""`.

```sh
coder provisioner start --org <organization_name>
```

If you omit the `--org` argument, the provisioner will be assigned to the
default organization.

```sh
coder provisioner start
```

### User-scoped Provisioners

**User-scoped Provisioners** can only pick up build jobs created from
user-tagged templates. Unlike the other provisioner types, any Coder user can
run user provisioners, but they have no impact unless there exists at least one
template with the `scope=user` provisioner tag.

```sh
coder provisioner start \
  --tag scope=user

# In another terminal, create/push
# a template that requires user provisioners
coder templates push on-prem \
  --provisioner-tag scope=user
```

## Example: Running an external provisioner with Helm

Coder provides a Helm chart for running external provisioner daemons, which you
will use in concert with the Helm chart for deploying the control plane.

1. Create a provisioner key:

   ```sh
   coder provisioner keys create my-cool-key --org default
   # Optionally, you can specify tags for the provisioner key:
   # coder provisioner keys create my-cool-key --org default --tag location=auh --tag kind=k8s

   Successfully created provisioner key kubernetes-key! Save this authentication
   token, it will not be shown again.

   <key omitted>
   ```

1. Store the key in a kubernetes secret:

   ```sh
   kubectl create secret generic coder-provisioner-keys --from-literal=my-cool-key=`<key omitted>`
   ```

1. Create a `provisioner-values.yaml` file for the provisioner daemons Helm
   chart. For example:

   ```yaml
   coder:
     env:
       - name: CODER_URL
         value: "https://coder.example.com"
     replicaCount: 10
   provisionerDaemon:
     # NOTE: in older versions of the Helm chart (2.17.0 and below), it is required to set this to an empty string.
     pskSecretName: ""
     keySecretName: "coder-provisioner-keys"
     keySecretKey: "my-cool-key"
   ```

   This example creates a deployment of 10 provisioner daemons (for 10
   concurrent builds) authenticating using the above key. The daemons will
   authenticate using the provisioner key created in the previous step and
   acquire jobs matching the tags specified when the provisioner key was
   created. The set of tags is inferred automatically from the provisioner key.

   > Refer to the
   > [values.yaml](../../../../helm/provisioner/values.yaml)
   > file for the coder-provisioner chart for information on what values can be
   > specified.

1. Install the provisioner daemon chart

   ```sh
   helm install coder-provisioner coder-v2/coder-provisioner \
       --namespace coder \
       --version <your version> \
       --values provisioner-values.yaml
   ```

   You can verify that your provisioner daemons have successfully connected to
   `coderd` by looking for a debug log message that says
   `provisioner: successfully connected to coderd` from each Pod.

## Example: Running an external provisioner on a VM

```sh
curl -fsSL https://coder.com/install.sh | sh
export CODER_URL=https://coder.example.com
export CODER_SESSION_TOKEN=your_token
coder provisioner start
```

## Example: Running an external provisioner via Docker

```sh
docker run --rm -it \
  -e CODER_URL=https://coder.example.com/ \
  -e CODER_SESSION_TOKEN=your_token \
  --entrypoint /opt/coder \
  ghcr.io/coder/coder:latest \
  provisioner start
```

## Disable built-in provisioners

As mentioned above, the control plane will run built-in provisioners by default.
This can be disabled with a server-wide
[flag or environment variable](../../../reference/cli/server/index.md#--provisioner-daemons).

```sh
coder server --provisioner-daemons=0
```

## Prometheus metrics

Coder provisioner daemon exports metrics via the HTTP endpoint, which can be
enabled using either the environment variable `CODER_PROMETHEUS_ENABLE` or the
flag `--prometheus-enable`.

The Prometheus endpoint address is `http://localhost:2112/` by default. You can
use either the environment variable `CODER_PROMETHEUS_ADDRESS` or the flag
`--prometheus-address <network-interface>:<port>` to select a different listen
address.

If you have provisioners daemons deployed as pods, it is advised to monitor them
separately.

## Next

- [Manage Provisioners](./manage-provisioner-jobs.md)

---

# Manage provisioner jobs

Source: https://coder.com/docs/install/operate/provisioners/manage-provisioner-jobs

[Provisioners](./index.md) start and run provisioner jobs to create or delete workspaces.
Each time a workspace is built, rebuilt, or destroyed, it generates a new job and assigns
the job to an available provisioner daemon for execution.

While most jobs complete smoothly, issues with templates, cloud resources, or misconfigured
provisioners can cause jobs to fail or hang indefinitely (these are in a `Pending` state).

![Provisioner jobs in the dashboard](../../../images/admin/provisioners/provisioner-jobs.png)

## How to find provisioner jobs

Coder admins can view and manage provisioner jobs.

Use the dashboard, CLI, or API:

- **Dashboard**:

   Select **Admin settings** > **Organizations** > **Provisioner Jobs**

   Provisioners are organization-specific. If you have more than one organization, select it first.

- **CLI**: `coder provisioner jobs list`
- **API**: `/api/v2/provisioner/jobs`

## Manage provisioner jobs from the dashboard

View more information about and manage your provisioner jobs from the Coder dashboard.

1. Under **Admin settings** select **Organizations**, then select **Provisioner jobs**.

1. Select the **>** to expand each entry for more information.

1. To delete a job, select the 🚫 at the end of the entry's row.

   If your user doesn't have the correct permissions, this option is greyed out.

## Provisioner job status

Each provisioner job has a lifecycle state:

| Status        | Description                                                    |
|---------------|----------------------------------------------------------------|
| **Pending**   | Job is queued but has not yet been picked up by a provisioner. |
| **Running**   | A provisioner is actively working on the job.                  |
| **Completed** | Job succeeded.                                                 |
| **Failed**    | Provisioner encountered an error while executing the job.      |
| **Canceled**  | Job was manually terminated by an admin.                       |

The following diagram shows how a provisioner job transitions between lifecycle states:

![Provisioner jobs state transitions](../../../images/admin/provisioners/provisioner-jobs-status-flow.png)

## When to cancel provisioner jobs

A job might need to be cancelled when:

- It has been stuck in **Pending** for too long. This can be due to misconfigured tags or unavailable provisioners.
- It is **Running** indefinitely, often caused by external system failures or buggy templates.
- An admin wants to abort a failed attempt, fix the root cause, and retry provisioning.
- A workspace was deleted in the UI but the underlying cloud resource wasn’t cleaned up, causing a hanging delete job.

Cancelling a job does not automatically retry the operation.
It clears the stuck state and allows the admin or user to trigger the action again if needed.

## Troubleshoot provisioner jobs

Provisioner jobs can fail or slow workspace creation for a number of reasons.
Follow these steps to identify problematic jobs or daemons:

1. Filter jobs by `pending` status in the dashboard, or use the CLI:

   ```sh
   coder provisioner jobs list -s pending
   ```

1. Look for daemons with multiple failed jobs and for template [tag mismatches](./index.md#provisioner-tags).

1. Cancel the job through the dashboard, or use the CLI:

   ```sh
   coder provisioner jobs cancel <job-id>
   ```

---

# Upgrade

Source: https://coder.com/docs/install/operate/upgrade

This article describes how to upgrade your Coder deployment.

> [!CAUTION]
> Prior to upgrading a production Coder deployment, take a database snapshot since
> Coder does not support rollbacks.

For upgrade recommendations and troubleshooting, see
[Upgrading Best Practices](./upgrade/best-practices.md).

## Reinstall Coder to upgrade

To upgrade your Coder deployment, reinstall Coder using your original method
of [install](../index.md).

### Coder install script

1. If you installed Coder using the `install.sh` script, re-run the below command
   on the host:

   ```sh
   curl -fsSL https://coder.com/install.sh | sh
   ```

1. If you're running Coder as a system service, you can restart it with `systemctl`:

   ```sh
   systemctl daemon-reload
   systemctl restart coder
   ```

### Other upgrade methods

<div class="tabs">

### docker-compose

If you installed using `docker-compose`, run the below command to upgrade the
Coder container:

```sh
docker-compose pull coder && docker-compose up -d coder
```

### Kubernetes

See
[Upgrade Coder via Helm](../server/kubernetes/index.md#upgrade-coder-via-helm).

### Coder AMI on AWS

1. Run the Coder installation script on the host:

   ```sh
   curl -fsSL https://coder.com/install.sh | sh
   ```

   The script will unpack the new `coder` binary version over the one currently
   installed.

1. Restart the Coder system process with `systemctl`:

   ```sh
   systemctl daemon-reload
   systemctl restart coder
   ```

### Windows

Download the latest Windows installer or binary from
[GitHub releases](https://github.com/coder/coder/releases/latest), or upgrade
from Winget.

```ps1
winget install Coder.Coder
```

</div>

---

# Upgrade best practices

Source: https://coder.com/docs/install/operate/upgrade/best-practices

This guide provides best practices for upgrading Coder, along with
troubleshooting steps for common issues encountered during upgrades,
particularly with database migrations in high availability (HA) deployments.

## Before you upgrade

> [!TIP]
> To check your current Coder version, use `coder version` from the CLI, check
> the bottom-right of the Coder dashboard, or query the `/api/v2/buildinfo`
> endpoint. See the [version command](../../../reference/cli/version.md) for details.

- **Schedule upgrades during off-peak hours.** Upgrades can cause a noticeable
  disruption to the developer experience. Plan your maintenance window when
  the fewest developers are actively using their workspaces.
- **The larger the version jump, the more migrations will run.** If you are
  upgrading across multiple minor versions, expect longer migration times.
- **Large upgrades should complete in minutes** (typically 4-7&nbsp;minutes).
  If your upgrade is taking significantly longer, there may be an issue requiring investigation.
- **Check for known issues affecting your upgrade path.** Some version upgrades
  have known issues that may require a larger maintenance window or additional
  steps. For example, upgrades from v2.26.0 to v2.27.8 may encounter issues with
  the `api_keys` table—upgrading to v2.26.6 first can help mitigate this.
  Contact [Coder support](../../../support/index.md) for guidance on your specific
  upgrade path.

## Pre-upgrade strategy for Kubernetes HA deployments

Standard Kubernetes rolling updates may fail when exclusive database locks are
required because old replicas keep connections open. For production deployments
running multiple replicas (HA), active connections from existing pods can
prevent the new pod from acquiring necessary locks.

### Recommended strategy for major upgrades

1. **Scale down before upgrading:** Before running `helm upgrade`, scale your
   Coder deployment down to eliminate database connection contention from
   existing pods.

   - **Scale to zero** for a clean cutover with no active database connections
     when the upgrade starts. This momentarily ensures no application access to
     the database, allowing migrations to acquire locks immediately:

     ```sh
     kubectl scale deployment coder --replicas=0
     ```

   - **Scale to one** if you prefer to minimize downtime. This keeps one pod
     running but eliminates contention from multiple replicas:

     ```sh
     kubectl scale deployment coder --replicas=1
     ```

1. **Perform upgrade:** Run your standard Helm upgrade command. When scaling to
   zero, this will bring up a fresh pod that can run migrations without
   competing for database locks.

1. **Scale back:** Once the upgrade is healthy, scale back to your desired
   replica count.

## Kubernetes liveness probes and long-running migrations

Liveness probes can cause pods to be killed during long-running database
migrations. Starting with Coder v2.30.0, liveness probes are *disabled by
default* in the Helm chart.

This change was made because:

- Liveness probes can kill pods during legitimate long-running migrations
- If a Coder pod becomes unresponsive (due to a deadlock, etc.), it's better to
  investigate the issue rather than have Kubernetes silently restart the pod

If you have enabled liveness probes in your deployment and observe pods
restarting with `CrashLoopBackOff` during an upgrade, the liveness probe may be
killing the pod prematurely.

<a id="diagnosing-liveness-probe-issues"></a>

### Diagnose liveness probe issues

To confirm whether Kubernetes is killing pods due to liveness probe failures,
check the Kubernetes events and pod logs:

```sh
# Check events for the Coder deployment
kubectl get events --field-selector involvedObject.name=coder -n <namespace>

# Check pod logs for migration progress
kubectl logs -l app.kubernetes.io/name=coder -n <namespace> --previous
```

Look for events indicating `Liveness probe failed` or `Container coder failed
liveness probe, will be restarted`.

### Recommended approach

If you have liveness probes enabled and experience issues during upgrades,
disable them before upgrading:

```sh
kubectl edit deployment coder
```

Remove the `livenessProbe` section entirely, then proceed with the upgrade.

> [!NOTE]
> For versions prior to v2.30.0, liveness probes were enabled by default. You
> can disable them by editing the Deployment directly with `kubectl edit
> deployment coder` or by using a ConfigMap override. See the
> [Helm chart values](https://artifacthub.io/packages/helm/coder-v2/coder?modal=values&path=coder.livenessProbe)
> for configuration options available in v2.30.0+.

### Workaround steps

1. **Remove or adjust liveness probes:** Temporarily remove the `livenessProbe`
   from your Deployment configuration to prevent Kubernetes from restarting the
   pod during migrations.

1. **Isolate the migration:** Ensure all extra replica sets are shut down. If
   you have clear evidence of database locks from old pods, scale the deployment
   to 1 replica to prevent old pods from holding locks on the tables being
   upgraded.

1. **Clear database locks:** Monitor database activity. If the migration remains
   blocked by locks despite scaling down, you may need to manually terminate
   existing connections. See
   [Recover from failed database migrations](#recover-from-failed-database-migrations)
   below for instructions.

<a id="recovering-from-failed-database-migrations"></a>

## Recover from failed database migrations

If an upgrade gets stuck in a restart loop due to database locks:

1. **Scale to zero:** Scale the Coder deployment to 0 to stop all application
   activity.

   ```sh
   kubectl scale deployment coder --replicas=0
   ```

1. **Clear connections:** Terminate existing connections to the Coder database
   to release any lingering locks. This PostgreSQL command drops all active
   connections to the database:

   > [!CAUTION]
   > This command is intrusive and should be used as a last resort. Contact
   > [Coder support](../../../support/index.md) before running destructive database
   > commands in production. SQL commands may vary depending on your PostgreSQL
   > version and configuration.

   ```sql
   SELECT pg_terminate_backend(pid)
   FROM pg_stat_activity
   WHERE datname = 'coder'
   AND pid <> pg_backend_pid();
   ```

1. **Check schema migrations:** Verify the level of upgrade and check if `dirty`
   is true. If this has progressed, this now indicates your current Coder
   installation state.

   > [!NOTE]
   > The SQL commands below are for informational purposes. If you are unsure
   > about querying your database directly, contact
   > [Coder support](../../../support/index.md) for assistance.

   ```sql
   SELECT * FROM schema_migrations;
   ```

1. **Ensure image version:** Confirm the Deployment image is set to the
   appropriate version (old or new, depending on the database migration state
   found in step 3). Match your tag in the
   [migrations directory](../../../../coderd/database/migrations)
   to the value in the `schema_migrations` output.

1. **Resume the upgrade:** Follow the
   [pre-upgrade strategy](#recommended-strategy-for-major-upgrades) to scale
   back up and continue the upgrade process.

## When to contact support

If you encounter any of the following issues, contact
[Coder support](../../../support/index.md):

- Locking issues that cannot be mitigated by the steps in this guide
- Migrations taking significantly longer than expected (more than 15&nbsp;minutes) without evidence of lock contention, which may indicate database resource constraints requiring investigation
- Resource consumption issues (excessive memory, CPU, or OOM kills) during
  upgrades
- Any other upgrade problems not covered by this documentation

When contacting support, please collect and provide:

- `coderd` logs with details on the stages where the upgrade stalled
- PostgreSQL logs if available
- The Coder versions involved (source and target)
- Your deployment configuration (number of replicas, resource limits)

---

# Upgrade from ESR 2.24 to 2.29

Source: https://coder.com/docs/install/operate/upgrade/esr-2.24-2.29-upgrade

## Guide Overview

Coder provides Extended Support Releases (ESR) bianually. This guide walks
through upgrading from the initial Coder 2.24 ESR to our new 2.29 ESR. It will
summarize key changes, highlight breaking updates, and provide a recommended
upgrade process.

Read more about the ESR release process
[here](../../../reference/releases.md#extended-support-release), and how Coder supports it.

## What's New in Coder 2.29

### Coder Tasks

Coder Tasks is an interface for running and interfacing with terminal-based
coding agents like Claude Code and Codex, powered by Coder workspaces. Beginning
in Coder 2.24, Tasks were introduced as an experimental feature that allowed
administrators and developers to run long-lived or automated operations from
templates. Over subsequent releases, Tasks matured significantly through UI
refinement, improved reliability, and underlying task-status improvements in the
server and database layers. By 2.29, Tasks were formally promoted to general
availability, with full CLI support, a task-specific UI, and consistent
visibility of task states across the dashboard. This transition established
Tasks as a stable automation and job-execution primitive within Coder,
particularly suited for long-running background operations like bug fixes,
documentation generation, PR reviews, and testing/QA.

> [!NOTE]
> Coder Tasks has since been deprecated and is no longer available in current
> releases. [Coder Agents](../../../ai-coder/agents/index.md) is the long-term
> replacement.

### AI Gateway

AI Gateway was introduced in 2.26, and is a smart gateway that acts as an
intermediary between users' coding agents/IDEs and AI providers like OpenAI and
Anthropic. It solves three key problems:

- Centralized authentication/authorization management (users authenticate via
  Coder instead of managing individual API tokens)
- Auditing and attribution of all AI interactions (whether autonomous or
  human-initiated)
- Secure communication between the Coder control plane and upstream AI APIs

This is a Premium/Beta feature that intercepts AI traffic to record prompts,
token usage, and tool invocations. For more information, read our documentation
[here](../../../ai-coder/ai-gateway/index.md).

### Agent Firewall

Agent Firewall was introduced in 2.27 and is currently in Early Access. Agent
Firewall is a process-level firewall in Coder that restricts and audits what
autonomous programs (like AI agents) can access and do within a workspace. They
provide network policy enforcement—blocking specific domains and HTTP verbs to
prevent data exfiltration—and write logs to the workspace for auditability.
Agent Firewall supports any terminal-based agent, including custom ones, and can be
easily configured through existing Coder modules like the Claude Code module.
For more information, read our documentation
[here](../../../ai-coder/agent-firewall/index.md).

### Performance Enhancements

Performance, particularly at scale, improved across nearly every system layer.
Database queries were optimized, several new indexes were added, and expensive
migrations—such as migration 371—were reworked to complete faster on large
deployments. Caching was introduced for Terraform installer files and
workspace/agent lookups, reducing repeated calls. Notification performance
improved through more efficient connection pooling. These changes collectively
enable deployments with hundreds or thousands of workspaces to operate more
smoothly and with lower resource contention.

### Server and API Updates

Core server capabilities expanded significantly across the releases. Prebuild
workflows gained timestamp-driven invalidation via last_invalidated_at, expired
API keys began being automatically purged, and new API key-scope documentation
was introduced to help administrators understand authorization boundaries. New
API endpoints were added, including the ability to modify a task prompt or look
up tasks by name. Template developers benefited from new Terraform
directory-persistence capabilities (opt-in on a per-template basis) and improved
`protobuf` configuration metadata.

### CLI Enhancements

The CLI gained substantial improvements between the two versions. Most notably,
beginning in 2.29, Coder’s CLI now stores session tokens in the operating system
keyring by default on macOS and Windows, enhancing credential security and
reducing exposure from plaintext token storage. Users who rely on directly
accessing the token file can opt out using `--use-keyring=false`. The CLI also
introduced cross-platform support for keyring storage, gained support for GA
Task commands, and integrated experimental functionality for the new Agent
Socket API.

## Changes to be Aware of

The following are changes introduced after 2.24.X that might break workflows, or
require other manual effort to address:

| Initial State (2.24 & before)                                      | New State (2.25-2.29)                                                                                  | Change Required                                                                                                                                                                                                                                                                 |
|--------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Workspace updates occur in place without stopping                  | Workspace updates now forcibly stop workspaces before updating                                         | Expect downtime during updates; update any scripted update flows that rely on seamless updates. See [`coder update` CLI reference](https://coder.com/docs/reference/cli/update).                                                                                                |
| Connection events (SSH, port-forward, browser) logged in Audit Log | Connection events moved to Connection Log; historical entries older than 90&nbsp;days pruned           | Update compliance, audit, or ingestion pipelines to use the new [Connection Log](https://coder.com/docs/admin/monitoring/connection-logs) instead of [Audit Logs](https://coder.com/docs/admin/security/audit-logs) for connection events.                                      |
| CLI session tokens stored in plaintext file                        | CLI session tokens stored in OS keyring (macOS/Windows)                                                | Update scripts, automation, or SSO flows that read/modify the token file, or use `--use-keyring=false`. See [Sessions & API Tokens](https://coder.com/docs/admin/users/sessions-tokens) and [`coder login` CLI reference](https://coder.com/docs/reference/cli/login).          |
| `task_app_id` field available in `codersdk.WorkspaceBuild`         | `task_app_id` removed from `codersdk.WorkspaceBuild`                                                   | Migrate integrations to use `Task.WorkspaceAppID` instead. See [REST API reference](https://coder.com/docs/reference/api).                                                                                                                                                      |
| OIDC session handling more permissive                              | Sessions expire when access tokens expire (typically 1&nbsp;hour) unless refresh tokens are configured | Add `offline_access` to `CODER_OIDC_SCOPES` (e.g., `openid,profile,email,offline_access`); Google requires `CODER_OIDC_AUTH_URL_PARAMS='{"access_type":"offline","prompt":"consent"}'`. See [OIDC Refresh Tokens](https://coder.com/docs/admin/users/oidc-auth/refresh-tokens). |
| Devcontainer agent selection is random when multiple agents exist  | Devcontainer agent selection requires explicit choice                                                  | Update automated workflows to explicitly specify agent selection. See [Dev Containers Integration](https://coder.com/docs/user-guides/devcontainers) and [Configure a template for dev containers](https://coder.com/docs/admin/templates/extending-templates/devcontainers).   |
| Terraform execution uses clean directories per build               | Terraform workflows use persistent or cached directories when enabled                                  | Update templates that rely on clean execution directories or per-build isolation. See [External Provisioners](https://coder.com/docs/admin/provisioners) and [Template Dependencies](https://coder.com/docs/admin/templates/managing-templates/dependencies).                   |
| Agent and task lifecycle behaviors more permissive                 | Agent and task lifecycle behaviors enforce stricter permission checks, readiness gating, and ordering  | Review workflows for compatibility with stricter readiness and permission requirements. See [Workspace Lifecycle](https://coder.com/docs/user-guides/workspace-lifecycle) and [Extending Templates](https://coder.com/docs/admin/templates/extending-templates).                |

<a id="upgrading"></a>

## Upgrade recommendations

The following are recommendations by the Coder team when performing the upgrade:

- **Perform the upgrade in a staging environment first:** The cumulative changes
  between 2.24 and 2.29 introduce new subsystems and lifecycle behaviors, so
  validating templates, authentication flows, and workspace operations in
  staging helps avoid production issues
- **Audit scripts or tools that rely on the CLI token file:** Since 2.29 uses
  the OS keyring for session tokens on macOS and Windows, update any tooling
  that reads the plaintext token file or plan to use `--use-keyring=false`
- **Review templates using devcontainers or Terraform:** Explicit agent
  selection, optional persistent/cached Terraform directories, and updated
  metadata handling mean template authors should retest builds and startup
  behavior
- **Check and update OIDC provider configuration:** Stricter refresh-token
  requirements in later releases can cause unexpected logouts or failed CLI
  authentication if providers are not configured according to updated docs
- **Update integrations referencing deprecated API fields:** Code relying on
  `WorkspaceBuild.task_app_id` must migrate to `Task.WorkspaceAppID`, and any
  custom integrations built against 2.24 APIs should be validated against the
  new SDK
- **Communicate audit-logging changes to security/compliance teams:** From 2.25
  onward, connection events moved into the Connection Log, and older audit
  entries may be pruned, which can affect SIEM pipelines or compliance workflows
- **Validate workspace lifecycle automation:** Since updates now require
  stopping the workspace first, confirm that automated update jobs, scripts, or
  scheduled tasks still function correctly in this new model
- **Retest agent and task automation built on early experimental features:**
  Updates to agent readiness, permission checks, and lifecycle ordering may
  affect workflows developed against 2.24’s looser behaviors
- **Monitor workspace, template, and Terraform build performance:** New caching,
  indexes, and DB optimizations may change build times; observing performance
  post-upgrade helps catch regressions early
- **Prepare user communications around Tasks and UI changes:** Tasks are now GA
  and more visible in the dashboard, and many UI improvements will be new to
  users coming from 2.24, so a brief internal announcement can smooth the
  transition

---

# Upgrade from ESR 2.29 to 2.34

Source: https://coder.com/docs/install/operate/upgrade/esr-2.29-2.34-upgrade

## Guide Overview

Coder provides Extended Support Releases (ESR) biannually. This guide walks
through upgrading from Coder 2.29 ESR to Coder 2.34 ESR. It
summarizes key changes, highlights breaking updates, and provides a recommended
upgrade process.

Read more about the
[ESR release process](../../../reference/releases.md#extended-support-release) and how Coder
supports it.

## What's New in Coder 2.34

### Coder Agents

[Coder Agents](../../../ai-coder/agents/index.md) was introduced in v2.32, and is the long-term replacement for
Coder Tasks. Coder Agents is a native AI coding agent that runs entirely within the Coder control plane, managing the agent loop, conversation state, and workspace provisioning in one place. This gives administrators centralized control over model access, credentials, and audit trails across every agent session. Coder Agents was made Beta in v2.33.

Coder Agents includes the following high-level functionality:

- Supports all major LLM providers
- Multi-turn chat
- Automatic workspace provisioning
- MCP server integration, personal skills, and administrator-managed skills
- ACL-based chat sharing across users and groups
- Admin-configurable advisor for planning and architecture guidance
- Plan and subagent explore modes
- Chat debugging
- Virtual desktop

Administrators have the following levers to configure appropriate access to various parts of Coder Agents:

- Template allow lists for agents
- BYOK for users
- Cost controls
- Configurable chat retention
- Automatic chat archiving
- Configurable system instructions
- Observability via AI Gateway, part of Coder's AI Governance features

> [!CAUTION]
> Coder Tasks is officially deprecated in 2.34. It remains supported through the 2.34 ESR support window
> but receives no new features. Coder recommends migrating to Coder Agents
> and the Chats API now. See the [Tasks to Chats migration guide](../../../ai-coder/agents/tasks-to-chats-migration.md)
> for API migration details.

### AI Gateway and AI Governance

AI Gateway, previously AI Bridge, matured into a broader governance and
observability layer for AI usage. It now supports:

- [AI Gateway Proxy](../../../ai-coder/ai-gateway/ai-gateway-proxy/index.md).
- OpenAI Responses API interception.
- Expanded Copilot and ChatGPT support.
- Custom Bedrock endpoints.
- Structured logs and client/session views.
- Model filtering.
- Multiple providers of the same type.
- [BYOK](../../../ai-coder/ai-gateway/auth.md#bring-your-own-key-byok) and
  [key failover](../../../ai-coder/ai-gateway/providers.md#key-failover).

[AI Governance](../../../ai-coder/ai-governance.md) adds administrative controls
around AI usage:

- License and seat visibility.
- AI session auditing.

These features help administrators understand who is using AI tools, which
providers are being used, and how spend changes over time.

For more information, visit the
[AI Gateway documentation](../../../ai-coder/ai-gateway/index.md).

### Agent Firewall

Agent Firewall, previously Agent Boundaries, moved from an early capability into
a stronger governance primitive for AI agents. It can audit and restrict network
access from agent processes, forward machine-readable logs to the control plane,
track usage, and use [landjail mode](../../../ai-coder/agent-firewall/landjail.md)
for environments where changing Linux capabilities is not practical.

For more information, visit the
[Agent Firewall documentation](../../../ai-coder/agent-firewall/index.md).

### Service Accounts

[Service accounts](../../../admin/users/headless-auth.md) are a
[Premium](../../prepare/licensing.md) feature and now integrate with workspace
sharing, user and workspace filtering, organization membership, and role
assignment.

### Templates, Prebuilds, and User Secrets

Template and workspace operations received several improvements:

- Terraform modules are [cached per template version](../../../tutorials/best-practices/speed-up-templates.md)
  to reduce repeated downloads and make workspace starts more deterministic.
- [Prebuild](../../../admin/templates/extending-templates/prebuilt-workspaces.md)
  claiming is more durable and idempotent.
- Prebuild presets are validated with dynamic parameter validation.
- [`coder_env`](../../../admin/templates/extending-templates/environment-variables.md)
  supports `merge_strategy`.
- [User secrets](../../../user-guides/user-secrets.md) can be created, encrypted,
  audited, and injected into workspaces.
- The dashboard warns about active prebuilds when duplicating templates.

These changes reduce operational surprises for template authors, but templates
that assumed a clean Terraform module download on every build should be tested.

### Security and Networking

Coder added several security and networking controls between 2.29 and 2.34:

- OAuth2 external auth providers now support PKCE, and unknown providers default
  to PKCE unless explicitly disabled.
- Secure auth cookies are now enabled automatically when `CODER_ACCESS_URL` uses
  HTTPS.
- AI Gateway Proxy blocks CONNECT tunnels to private or reserved IP ranges, while
  always exempting the Coder access URL.
- Workspace agents can disable reverse and local port forwarding through agent
  flags.
- Authenticated request rate limiting is keyed by user instead of IP address.
- Kubernetes Gateway API `HTTPRoute` is supported as an alternative to Ingress.
- Helm chart probes are more configurable, and Prometheus and pprof addresses can
  be overridden through chart environment values.
- DERP TLS configuration is wired through the CLI, SDK, tailnet, VPN, agent, and
  health checks.

### Operations and Scale

Large deployments should now have improvements in database, logging, and
observability behavior. Coder added the following:

- Configurable PostgreSQL connection pool settings.
- [Retention configuration](../../../admin/setup/data-retention.md) for audit logs,
  connection logs, API keys, and workspace agent logs.
- `dbpurge` metrics.
- Support bundle improvements.
- `chatd` metrics.
- Agent first-connection duration metrics.
- A `coder_build_info` metric.

Coder also removed several deprecated Prometheus metrics, so dashboards and
alerts should be reviewed before the upgrade.

Several expensive queries and write paths were optimized, including:

- AI Gateway session listing.
- Audit and connection log counts.
- Connection log batching.
- Provisioner job queue lookups.
- Chat streaming.
- Coordinator peer mapping.

### CLI and Dashboard Enhancements

The CLI and dashboard gained smaller but meaningful workflow improvements:

- `coder create --no-wait` creates a workspace without waiting for startup.
- `coder logs` provides easier access to logs.
- `coder login token` prints the current session token for scripts and automation.
- `coder support bundle` can infer the workspace from the environment.
- `coder groups list -o json` now returns a flat JSON structure.
- The dashboard includes user editing, service account management, group member
  filtering, role selection during user creation, improved accessibility, and
  clearer confirmation flows for destructive actions.

## Changes to be Aware of

The following changes introduced after 2.29 might break workflows, require manual
updates, or change administrator expectations:

| Initial State (2.29 and before)                                                                                 | New State (2.30-2.34)                                                                                                                                       | Change Required                                                                                                                                                                                                                                                                                |
|-----------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Terraform modules are downloaded during each workspace start.                                                   | Terraform modules are cached and pinned per template version.                                                                                               | Publish a new template version when upstream module changes should apply. Test templates that relied on fresh module downloads. See [speed up templates](../../../tutorials/best-practices/speed-up-templates.md).                                                                             |
| Integrations may use experimental AI Bridge endpoints under `/api/experimental/aibridge/*`.                     | Experimental AI Bridge endpoints were removed after AI Gateway graduated to stable routes.                                                                  | Update clients to use `/api/v2/aibridge/*` routes. Review API consumers again because `/api/v2/aibridge/interceptions` is now deprecated in favor of `/api/v2/aibridge/sessions`. See the [AI Gateway API reference](../../../reference/api/aigateway.md).                                     |
| Unknown external OAuth providers did not default to PKCE.                                                       | Unknown external OAuth providers now default to PKCE.                                                                                                       | If a provider does not support PKCE, set `CODER_EXTERNAL_AUTH_<N>_PKCE_METHODS=none`. See [external authentication](../../../admin/external-auth/index.md).                                                                                                                                    |
| GitLab external auth required only the `write_repository` scope.                                                | GitLab external auth now requires `write_repository` and `read_api` scopes by default.                                                                      | Add the `read_api` scope to your GitLab OAuth application. Existing users must re-authenticate to obtain the new scope. If you set scopes explicitly via `CODER_EXTERNAL_AUTH_<N>_SCOPES`, add `read_api` there as well. See [external authentication](../../../admin/external-auth/index.md). |
| `--secure-auth-cookie` defaulted independently from the access URL.                                             | Secure auth cookies are enabled automatically when `CODER_ACCESS_URL` uses HTTPS.                                                                           | Confirm reverse proxies send the correct scheme headers. To preserve old behavior, explicitly set `CODER_SECURE_AUTH_COOKIE=false`.                                                                                                                                                            |
| SFTP and SCP connections always landed in `$HOME`.                                                              | SFTP and SCP now respect the workspace agent `dir` setting.                                                                                                 | Update scripts that relied on implicit `$HOME` paths. Prefer explicit absolute paths for file transfers.                                                                                                                                                                                       |
| `coder_agent` `dir` attribute accepted any path without warning.                                                | `dir` is deprecated and emits a warning. Non-`$HOME`/`~` values also break [Coder Desktop file sync](../../../user-guides/desktop/desktop-connect-sync.md). | Set `dir` to `$HOME` or omit it on `coder_agent` resources. The attribute still works in 2.34 but will be removed in a future release.                                                                                                                                                         |
| Pre-2.28 Tasks templates might still exist in older deployments.                                                | The pre-2.28 Tasks template format is no longer supported as of 2.30.                                                                                       | Update Tasks templates to use `app_id` instead of the deprecated `sidebar_app` flow.                                                                                                                                                                                                           |
| Tasks is the primary AI coding workflow.                                                                        | Coder Agents is the long-term replacement, and Tasks is supported through the 2.34 ESR window (into 2026).                                                  | Plan migration from the Tasks API to the Chats API and [Coder Agents](../../../ai-coder/agents/index.md). See [Migrating from the Tasks API to the Chats API](../../../ai-coder/agents/tasks-to-chats-migration.md).                                                                           |
| AI Gateway injected MCP tools can be used for tool exposure.                                                    | Injected MCP tools are deprecated.                                                                                                                          | Move new integrations toward Coder Agents MCP server configuration or the MCP server flow. See [AI Gateway MCP](../../../ai-coder/ai-gateway/mcp.md) and [MCP servers](../../../ai-coder/agents/platform-controls/mcp-servers.md).                                                             |
| AI Bridge is opt-in via `CODER_AIBRIDGE_ENABLED` (default `false`).                                             | The toggle is renamed to `CODER_AI_GATEWAY_ENABLED` and now defaults to `true`.                                                                             | The in-memory AI Gateway now starts on every deployment. Set `CODER_AI_GATEWAY_ENABLED=false`, or the deprecated `CODER_AIBRIDGE_ENABLED` alias which still works, to keep the old behavior.                                                                                                   |
| AI Gateway providers are configured with `CODER_AIBRIDGE_PROVIDER_*` or `CODER_AI_GATEWAY_PROVIDER_*` env vars. | Provider configuration is stored in the database. Env vars seed the database once on first startup, then are deprecated.                                    | After upgrade, visit `/ai/settings/providers` to verify seeded providers, then remove the env vars. Coderd fails to start if env vars drift from the seeded database row. See [AI Gateway providers](../../../ai-coder/ai-gateway/providers.md).                                               |
| Regular users can read their own AI Gateway interceptions.                                                      | Only owners and auditors can read AI Gateway interception data.                                                                                             | Update dashboards, scripts, or user workflows that expected self-service interception reads. This intentionally narrows the RBAC surface.                                                                                                                                                      |
| `coder groups list -o json` returns the old command output shape.                                               | `coder groups list -o json` returns a flat structure matching other list commands.                                                                          | Update scripts that parse this command output.                                                                                                                                                                                                                                                 |
| `coder tokens rm` deletes token records by default.                                                             | `coder tokens rm` expires tokens by default and keeps records for auditability.                                                                             | Use `coder tokens rm --delete` only when the token record must be deleted. Update scripts that expect removed tokens to disappear from token history.                                                                                                                                          |
| Deprecated Prometheus metrics are still emitted.                                                                | Deprecated Prometheus metrics were removed.                                                                                                                 | Update dashboards and alerts that use `coderd_api_workspace_latest_build_total` or `coderd_oauth2_external_requests_rate_limit_total`. Use the replacement metrics without the `_total` suffix.                                                                                                |
| Authenticated rate limits are effectively shared by client IP in some deployments.                              | Authenticated request rate limits are keyed by user.                                                                                                        | Review monitoring and expectations for NATed users or shared proxies. Per-user limits now apply more consistently after API key precheck.                                                                                                                                                      |
| `coder login` can run while `CODER_SESSION_TOKEN` is set.                                                       | `coder login` errors when `CODER_SESSION_TOKEN` is set.                                                                                                     | Unset `CODER_SESSION_TOKEN` in interactive login flows. Keep using the environment variable for non-interactive automation.                                                                                                                                                                    |
| Workspace starts with new parameters can proceed without an explicit stop in some flows.                        | Workspace starts with new parameters stop the workspace before starting.                                                                                    | Expect downtime when applying new parameters. Update automation that assumes the workspace remains running.                                                                                                                                                                                    |
| `mode=auto` workspace links can silently create workspaces with prefilled parameters.                           | Users must confirm workspace auto-creation before provisioning starts.                                                                                      | Update Open in Coder buttons, runbooks, or internal flows that expect one-click workspace creation without a consent dialog.                                                                                                                                                                   |
| Users with `--login-type none` are common for automation.                                                       | `--login-type none` is deprecated.                                                                                                                          | For Premium deployments, migrate automation to service accounts. For OSS deployments, use regular users with password, GitHub, or OIDC authentication. See [headless auth](../../../admin/users/headless-auth.md).                                                                             |
| Terminal commands can be executed from URL parameters without extra confirmation.                               | The dashboard requires confirmation before executing terminal commands from URLs.                                                                           | Update runbooks or deep links that expected immediate terminal execution. This protects users from accidental command execution.                                                                                                                                                               |
| Agent SSH port forwarding is always available when the agent allows SSH.                                        | Reverse and local port forwarding can be disabled per agent.                                                                                                | Review templates and IDE workflows before enabling `--block-reverse-port-forwarding` or `--block-local-port-forwarding`. See [port forwarding](../../../admin/networking/port-forwarding.md).                                                                                                  |
| `PATCH /api/v2/templates/{template}` accepts value fields for metadata updates.                                 | Template metadata update fields are optional pointer fields in the SDK, and 304 responses were removed.                                                     | Update SDK consumers and direct API clients that patch template metadata. Send only fields that should change, including false or zero values explicitly.                                                                                                                                      |
| External provisioner daemons use the 2.29 provisionerd protocol.                                                | The provisionerd protocol changed for provisioner operations and file upload/download.                                                                      | Update external provisioner daemons to the matching 2.34 protocol. The protocol reserves removed fields such as `stop_modules`, `exp_reuse_terraform_workspace`, and `user_secrets`, and adds `DownloadFile`.                                                                                  |
| Helm chart health probes and observability bind addresses use older chart defaults.                             | Readiness and liveness probes have `enabled` toggles and more fields, and Prometheus/pprof addresses are overridable.                                       | Review custom Helm values for probe behavior and observability bindings. Prefer restricting pprof to a local address when exposing diagnostics.                                                                                                                                                |

<a id="upgrading"></a>

## Upgrade recommendations

> [!NOTE]
> You can upgrade directly from 2.29 to 2.34. Stepping through intermediate
> minor versions is not required.
>
> This upgrade applies 108 database migrations. Coder applies them in order
> on startup. Most are fast schema changes, but a few rewrite or backfill
> long-lived tables and hold locks while they run. Total time ranges from under
> a minute to several minutes, scaling with the size of the tables called out
> in [Database migrations to watch](#database-migrations-to-watch) below.
>
> Take a database backup before upgrading and validate the upgrade in a
> staging environment that mirrors production data volume.

### Database migrations to watch

The batch runs in order on the first startup of the new version. Most
migrations create new tables or make fast schema changes, but the following
pre-existing tables receive the heaviest operations. Size your maintenance
window for whichever are largest in your deployment:

- **Tailnet coordination tables** (`tailnet_peers`, `tailnet_tunnels`,
  `tailnet_coordinators`) are converted to `UNLOGGED` and rewritten under an
  exclusive lock. **`UNLOGGED` tables are not replicated to standby servers and
  are truncated on crash recovery.** This is intentional, since coordinators
  re-register and peers reconnect on startup, but confirm your high
  availability strategy does not rely on replicating tailnet state to read
  replicas.
- **`users`** gains a service account column plus check constraints and unique
  index rebuilds, held under an exclusive lock. This briefly blocks logins and
  API key validation, so the duration matters most on deployments with many
  users.
- **`workspace_agents`** (joined with `workspace_builds`, `workspace_resources`,
  and `workspaces`) is bulk updated to soft-delete stale agents left behind by
  a pre-2.33 bug. This is typically the slowest step on long-lived deployments
  with extensive build history. It is safe, but plan for the time.
- **`workspaces`** receives full-table updates and new ACL check constraints.
- **`usage_events`** has a check constraint revalidated and an index added; the
  cost scales with retained event volume.

Several of these changes are irreversible, including the `users` service
account reclassification and the cleanup of `user_secrets`,
`organization_members`, and related rows for already soft-deleted users. Take a
database backup before upgrading.

The Coder team recommends taking the following steps when performing the upgrade:

- **Perform the upgrade in a staging environment first:** The cumulative changes
  between 2.29 and 2.34 affect AI workflows, templates, prebuilds,
  authentication, RBAC, and dashboard behavior. Validate representative
  workspaces before production rollout.
- **Retest templates and prebuilds:** Focus on Terraform module caching,
  prebuild preset validation, `coder_env` merging, user secrets, and workspace
  starts with changed parameters.
- **Audit AI Gateway integrations:** Update experimental API routes, check
  permissions for interception/session data, migrate provider configuration
  from env vars to the database via `/ai/settings/providers`, verify proxy mode behavior,
  and review any injected MCP usage.
- **Plan the Tasks to Agents migration:** Tasks remains available during the
  support window, but new automation should use Coder Agents and the Chats API.
  Update internal docs, templates, and API clients accordingly.
- **Validate external authentication:** Test GitHub, GitLab, OIDC, and custom
  external auth providers. Add the `read_api` scope to GitLab OAuth applications
  and have users re-authenticate. Disable PKCE for providers that do not support
  it.
- **Migrate headless automation to service accounts:** Replace users created
  with `--login-type none` where possible, and verify CI/CD tokens, template
  publish jobs, and workspace automation.
- **Update CLI parsers, API clients, and scripts:** Check `coder groups list -o
  json`, `coder tokens rm`, `coder login` with `CODER_SESSION_TOKEN`, SFTP/SCP
  destination paths, template metadata update clients, provisionerd protocol
  consumers, and any script that depends on terminal command URL execution.
- **Review networking controls before enabling them:** Test AI Gateway Proxy,
  private IP restrictions, port forwarding blocks, DERP TLS configuration,
  Kubernetes `HTTPRoute`, and Helm probe settings in environments that use custom
  networking.
- **Tune operational settings after rollout:** Review PostgreSQL connection pool
  settings, retention policies, dbpurge behavior, Prometheus metrics, secure
  cookie behavior, support bundle output, and log ingestion pipelines.
- **Communicate user-facing changes:** Service accounts, Coder Agents, AI
  Governance, Tasks deprecation, dashboard confirmations, and workspace parameter
  restarts can change user workflows. Share the expected behavior before the
  production upgrade.

---

# Uninstall

Source: https://coder.com/docs/install/operate/uninstall

<!-- markdownlint-disable MD024 -->
This article walks you through how to uninstall Coder.

To uninstall Coder, delete the following directories.

## The Coder binary and CLI

<div class="tabs">

## Linux

<div class="tabs">

## Debian, Ubuntu

```sh
sudo apt remove coder
```

## Fedora, CentOS, RHEL, SUSE

```sh
sudo yum remove coder
```

## Alpine

```sh
sudo apk del coder
```

</div>

If you installed Coder manually or used the install script on an unsupported
operating system, you can remove the binary directly:

```sh
sudo rm /usr/local/bin/coder
```

## macOS

```sh
brew uninstall coder
```

If you installed Coder manually, you can remove the binary directly:

```sh
sudo rm /usr/local/bin/coder
```

## Windows

```ps1
winget uninstall Coder.Coder
```

</div>

## Coder as a system service configuration

```sh
sudo rm /etc/coder.d/coder.env
```

## Coder settings, cache, and the optional built-in PostgreSQL database

There is a `postgres` directory within the `coderv2` directory that has the
database engine and database. If you want to reuse the database, consider not
performing the following step or copying the directory to another location.

<div class="tabs">

## Linux

```sh
rm -rf ~/.config/coderv2
rm -rf ~/.cache/coder
```

## macOS

```sh
rm -rf ~/Library/Application\ Support/coderv2
```

## Windows

```ps1
rmdir %AppData%\coderv2
```

</div>

---

# User Guides

Source: https://coder.com/docs/user-guides

These guides contain information on workspace management, workspace access via
IDEs, environment personalization, and workspace scheduling.

These are intended for end-user flows only. If you are an administrator, please
refer to our docs on configuring [templates](../admin/index.md) or the
[control plane](../admin/index.md).

Check out [Dev Containers integration](./devcontainers/index.md) for running
containerized development environments in your Coder workspace.

<children></children>

---

# Access your workspace

Source: https://coder.com/docs/user-guides/workspace-access

There are many ways to connect to your workspace, the options are only limited
by the template configuration.

Deployment operators can learn more about different types of workspace
connections and performance in our
[networking docs](../../install/plan/index.md).

You can see the primary methods of connecting to your workspace in the workspace
dashboard.

![Workspace View](../../images/user-guides/workspace-view-connection-annotated.png)

## Web Terminal

The Web Terminal is a browser-based terminal that provides instant access to
your workspace's shell environment. It uses [xterm.js](https://xtermjs.org/)
and WebSocket technology for a responsive terminal experience with features
like persistent sessions, Unicode support, and clickable URLs.

![Terminal Access](../../images/user-guides/terminal-access.png)

Read the complete [Web Terminal documentation](./web-terminal.md) for
customization options, keyboard shortcuts, and troubleshooting guides.

## SSH

### Through the CLI

Coder will use the optimal path for an SSH connection (determined by your
deployment's [networking configuration](../../install/plan/index.md))
when using the CLI:

```console
coder ssh my-workspace
```

Or, you can configure plain SSH on your client below.

> [!NOTE]
> The `coder ssh` command does not have full parity with the standard
> SSH command. For users who need the full functionality of SSH, use the
> configuration method below.

<a id="running-remote-commands-with-quoting"></a>

### Run remote commands with quoting

Arguments after `--` are joined with spaces into a single command
string before being sent to the workspace agent (per
[RFC 4254 §6.5](https://www.rfc-editor.org/rfc/rfc4254#section-6.5),
which defines the SSH exec request as a single string). Your local
shell consumes outer quotes before the CLI ever sees the arguments,
so inner quoting is not preserved on the wire.

This means a common pattern from interactive shells does not behave
as you might expect:

```console
# Surprising: prints an empty line, NOT "ready"
coder ssh my-workspace -- bash -c 'echo ready'
```

The local shell strips the single-quotes, the CLI receives the argv
`[bash, -c, echo, ready]`, and the remote agent runs
`bash -c echo ready`; `echo` gets no arguments and `ready` is bound to
`$0`. The same caveat applies to plain `ssh user@host -- bash -c '...'`;
this is SSH protocol semantics, not a `coder ssh` limitation.

For commands that need preserved quoting, use one of these patterns:

**Heredoc via stdin** (recommended for multi-line scripts):

```console
coder ssh my-workspace -- bash <<'EOF'
echo ready
EOF
```

**A single-argument script payload**:

```console
coder ssh my-workspace -- /path/to/script.sh
```

**Exit-code-only probe** (when you only need to know if the command succeeded):

```console
coder ssh my-workspace -- true && echo "agent is reachable"
```

### Configure SSH

Coder generates [SSH key pairs](../../admin/security/secrets.md#ssh-keys) for
each user to simplify the setup process.

1. Use your terminal to authenticate the CLI with Coder web UI and your workspaces:

   ```sh
   coder login <accessURL>
   ```

1. Access Coder via SSH:

   ```sh
   coder config-ssh
   ```

1. Run `coder config-ssh --dry-run` if you'd like to see the changes that will be
   before you proceed:

   ```sh
   coder config-ssh --dry-run
   ```

1. Confirm that you want to continue by typing **yes** and pressing enter. If
successful, you'll see the following message:

   ```console
   You should now be able to ssh into your workspace.
   For example, try running:

   $ ssh coder.<workspaceName>
   ```

Your workspace is now accessible via `ssh coder.<workspace_name>`
(for example, `ssh coder.myEnv` if your workspace is named `myEnv`).

> [!TIP]
> If you use a third-party SSH client that discovers hosts by parsing
> `~/.ssh/config` (such as the VS Code Remote-SSH sidebar or scripts that
> enumerate known hosts), run `coder config-ssh --no-wildcard` instead. This
> generates an individual `Host` entry per workspace rather than a single
> wildcard block, making your workspaces visible to those tools.

## Visual Studio Code

You can develop in your Coder workspace remotely with
[VS Code](https://code.visualstudio.com/download).
We support connecting with the desktop client and VS Code in the browser with [code-server](#code-server).

![Demo](https://github.com/coder/vscode-coder/raw/main/demo.gif?raw=true)

Read more details on [using VS Code in your workspace](./vscode.md).

## Cursor

[Cursor](https://cursor.sh/) is an IDE built on VS Code with enhanced AI capabilities.
Cursor connects using the Coder extension.

Read more about [using Cursor with your workspace](./cursor.md).

## Devin Desktop

[Devin Desktop](./devin-desktop.md) (formerly Windsurf, formerly Codeium) is Cognition's AI-powered code editor designed for AI-assisted development.
Devin Desktop connects using the Coder extension.

## Antigravity

[Antigravity](https://antigravity.google/) is Google's desktop IDE.
Antigravity connects using the Coder extension.

Read more about [using Antigravity with your workspace](./antigravity.md).

## JetBrains IDEs

We support JetBrains IDEs using
[Gateway](https://www.jetbrains.com/remote-development/gateway/). The following
IDEs are supported for remote development:

- IntelliJ IDEA
- CLion
- GoLand
- PyCharm
- Rider
- RubyMine
- WebStorm

Read our [docs on JetBrains](./jetbrains/index.md) for more information
on connecting your JetBrains IDEs.

## code-server

[code-server](https://github.com/coder/code-server) is our supported method of
running VS Code in the web browser.
Learn more about [what makes code-server different from VS Code web](./code-server.md) or visit the
[documentation for code-server](https://coder.com/docs/code-server).

![code-server in a workspace](../../images/code-server-ide.png)

## Other Web IDEs

We support a variety of other browser IDEs and tools to interact with your
workspace. Each of these can be configured by your template admin using our
[Web IDE guides](../../admin/templates/extending-templates/web-ides.md).

Supported IDEs:

- VS Code Web
- JupyterLab
- RStudio
- Airflow
- File Browser

Our [Module Registry](https://registry.coder.com/modules) also hosts a variety
of tools for extending the capability of your workspace. If you have a request
for a new IDE or tool, please file an issue in our
[Modules repo](https://github.com/coder/registry/issues).

## Coder Desktop

[Coder Desktop](../desktop/index.md) is a native application that provides seamless access to your workspaces via a VPN tunnel. With Coder Desktop, you get:

- **Automatic port forwarding**: All workspace ports are available at `workspace-name.coder:PORT` with no manual setup
- **SSH access**: Connect with `ssh workspace-name.coder` using any SSH client
- **File sync**: Bidirectional file synchronization between local and remote directories

Coder Desktop is the recommended way to access workspace services for developers who want a seamless, native experience.

## Ports and Port forwarding

You can manage listening ports on your workspace page through the listening
ports window in the dashboard. These ports are often used to run internal
services or preview environments.

> [!TIP]
> For automatic access to all ports without manual configuration, use [Coder Desktop](../desktop/index.md).

You can also [share ports](./port-forwarding.md#share-ports) with other users,
or [port-forward](./port-forwarding.md#the-coder-port-forward-command) through
the CLI with `coder port-forward`. Read more in the
[docs on workspace ports](./port-forwarding.md).

![Open Ports window](../../images/networking/listeningports.png)

## Remote Desktops

Coder also supports connecting with an RDP solution, see our
[RDP guide](./remote-desktops.md) for details.

---

# Visual Studio Code

Source: https://coder.com/docs/user-guides/workspace-access/vscode

You can develop in your Coder workspace remotely with
[VS Code](https://code.visualstudio.com/download).
We support connecting with the desktop client and VS Code in the browser with
[code-server](https://github.com/coder/code-server).
Learn more about how VS Code Web and code-server compare in the
[code-server doc](./code-server.md).

## VS Code Desktop

VS Code desktop is a default app for workspaces.

Select **VS Code Desktop** in the dashboard to one-click enter a workspace.
This automatically installs the [Coder Remote](https://github.com/coder/vscode-coder) extension, authenticates with Coder, and connects to the workspace.

![Demo](https://github.com/coder/vscode-coder/raw/main/demo.gif?raw=true)

> [!NOTE]
> The `VS Code Desktop` button can be hidden by enabling
> [Browser-only connections](../../admin/networking/index.md#browser-only-connections).

### Manual Installation

You can install our extension manually in VS Code using the command palette.
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press
enter.

```txt
ext install coder.coder-remote
```

Alternatively, manually install the VSIX from the
[latest release](https://github.com/coder/vscode-coder/releases/latest).

## Local telemetry

The Coder Remote extension records local telemetry to help diagnose extension
and workspace connection issues. Telemetry is stored on your machine. It is not
sent to Coder unless you export it or include it in a support bundle and share
that file.

Local telemetry is controlled by the VS Code setting `coder.telemetry.level`:

| Value   | Behavior                                                      |
|---------|---------------------------------------------------------------|
| `off`   | Disable extension telemetry collection.                       |
| `local` | Record telemetry events on this machine. This is the default. |

### Stored data

Telemetry can include diagnostic details such as extension version, VS Code
version, operating system, machine and session identifiers, deployment URL,
workspace and agent names, command outcomes, connection state, request routes,
timing, and error details. It does not intentionally collect source code,
terminal contents, tokens, or credentials.

### Tracked activity

The exact events vary by extension version. For a comprehensive list of current
events, properties, and attributes, see the
[extension event reference](https://github.com/coder/vscode-coder/blob/main/src/instrumentation/EVENTS.md).
The following categories summarize the diagnostic signals the extension may
record:

| Area                           | Examples                                                                                     |
|--------------------------------|----------------------------------------------------------------------------------------------|
| Extension lifecycle            | Activation, deployment initialization, and configuration loading.                            |
| Authentication and credentials | Sign-in state, token refresh, logout, credential storage, and deployment recovery.           |
| Commands and diagnostics       | Command outcomes, telemetry exports, support bundle creation, ping, and speed tests.         |
| Workspace workflows            | Workspace selection, open attempts, dev container handoff, start, and update prompts.        |
| CLI and remote setup           | CLI binary resolution, download, verification, configuration, and setup through SSH handoff. |
| Connection health              | Workspace and agent state transitions, reconnects, SSH process health, and network samples.  |
| HTTP diagnostics               | Normalized routes, status classes, and latency rollups.                                      |

### Storage and retention

The extension stores telemetry as JSON Lines files in its VS Code global storage under a `telemetry` directory.
Files rotate at 5&nbsp;MiB, are kept for up to 30&nbsp;days, and are capped at 100&nbsp;MiB total by default.

You can tune local retention with the advanced `coder.telemetry.local` setting.
Most users should keep the default values.

### Diagnostics and support bundles

The extension includes commands for collecting diagnostics from VS Code:

- **Coder: Export Telemetry** exports only local telemetry. Choose a date range
  and JSON or OTLP JSON zip format, then review the file before sharing it.
- **Coder: Create Support Bundle** runs `coder support bundle` and adds a
  `vscode-logs/` directory with recent VS Code extension diagnostics, including
  extension logs, proxy and Remote-SSH logs, redacted VS Code settings, and
  local telemetry files when available. The `vscode-logs/` directory is only
  added when the bundle is created from the VS Code Coder Remote extension;
  bundles created with the CLI alone do not include it.
- **Coder: View Logs** opens the extension output logs in VS Code.

Support bundles can contain sensitive diagnostic data. Review the generated
bundle before sharing it. Learn more about
[support bundles](../../support/support-bundle.md).

## VS Code extensions

There are multiple ways to add extensions to VS Code Desktop:

1. Using the
   [public extensions marketplaces](#use-the-public-extensions-marketplaces)
   with Code Web (code-server)
1. Adding [extensions to custom images](#add-extensions-to-custom-images)
1. Installing extensions
   [using its `vsix` file at the command line](#install-extensions-using-a-vsix-file-at-the-command-line)
1. Installing extensions
   [from a marketplace using the command line](#install-from-a-marketplace-at-the-command-line)

<a id="using-the-public-extensions-marketplaces"></a>

### Use the public extensions marketplaces

You can manually add an extension while you're working in the Code Web IDE. The
extensions can be from Coder's public marketplace, Eclipse Open VSX's public
marketplace, or the Eclipse Open VSX _local_ marketplace.

![Code Web Extensions](../../images/ides/code-web-extensions.png)

> [!NOTE]
> Microsoft does not allow any unofficial VS Code IDE to connect to the
> extension marketplace.

<a id="adding-extensions-to-custom-images"></a>

### Add extensions to custom images

You can add extensions to a custom image and install them either through Code
Web or using the workspace's terminal.

1. Download the extension(s) from the Microsoft public marketplace.

   ![Code Web Extensions](../../images/ides/copilot.png)

1. Add the `vsix` extension files to the same folder as your Dockerfile.

   ```sh
   ~/images/base
    ➜  ls -l
    -rw-r--r-- 1 coder coder       0 Aug 1 19:23 Dockerfile
    -rw-r--r-- 1 coder coder 8925314 Aug 1 19:40 GitHub.copilot.vsix
   ```

1. In the Dockerfile, add instructions to make a folder and to copy the `vsix`
   files into the newly created folder.

   ```dockerfile
   FROM codercom/example-base:ubuntu

   # Run below commands as root user
   USER root

   # Download and install VS Code extensions into the container
   RUN mkdir -p /vsix
   ADD ./GitHub.copilot.vsix /vsix

   USER coder
   ```

1. Build the custom image, and push it to your image registry.

1. Pass in the image and below command into your template `startup_script` (be
   sure to update the filename below):

   **Startup Script**

   ```tf
   resource "coder_agent" "main" {
     ...
     startup_script = "code-server --install-extension /vsix/GitHub.copilot.vsix"
   }
   ```

   **Image Definition**

   ```tf
   resource "kubernetes_deployment" "main" {
     spec {
       template {
         spec {
           container {
             name   = "dev"
             image  = "registry.internal/image-name:tag"
           }
         }
       }
     }
   }
   ```

1. Create a workspace using the template.

You will now have access to the extension in your workspace.

<a id="installing-extensions-using-its-vsix-file-at-the-command-line"></a>

### Install extensions using a `vsix` file at the command line

Using the workspace's terminal or the terminal available inside `code-server`,
you can install an extension whose files you've downloaded from a marketplace:

```console
/path/to/code-server --install-extension /vsix/GitHub.copilot.vsix
```

<a id="installing-from-a-marketplace-at-the-command-line"></a>

### Install from a marketplace at the command line

Using the workspace's terminal or the terminal available inside Code Web (code
server), run the following to install an extension (be sure to update the
snippets with the name of the extension you want to install):

```console
SERVICE_URL=https://extensions.coder.com/api ITEM_URL=https://extensions.coder.com/item /path/to/code-server --install-extension GitHub.copilot
```

Alternatively, you can install an extension from Open VSX's public marketplace:

```console
SERVICE_URL=https://open-vsx.org/vscode/gallery ITEM_URL=https://open-vsx.org/vscode/item /path/to/code-server --install-extension GitHub.copilot
```

<a id="using-vs-code-desktop"></a>

### Use VS Code Desktop

For your local VS Code to pickup extension files in your Coder workspace,
include this command in your `startup_script`, or run in manually in your
workspace terminal:

```console
code --extensions-dir ~/.vscode-server/extensions --install-extension "$extension"
```

---

# Web Terminal

Source: https://coder.com/docs/user-guides/workspace-access/web-terminal

The Web Terminal is a browser-based terminal interface that provides instant
access to your workspace's shell environment directly from the Coder dashboard.
It's automatically enabled for all workspaces and requires no additional
configuration.

![Terminal Access](../../images/user-guides/terminal-access.png)

## Overview

The Web Terminal leverages [xterm.js](https://xtermjs.org/), an industry-standard
terminal emulator, combined with WebSocket technology to provide a responsive
and feature-rich terminal experience in your browser.

### Key Features

- **Instant Access**: Select the terminal icon in your workspace to open a shell
  session
- **Persistent Sessions**: Sessions are maintained using reconnection tokens,
  allowing you to resume your terminal even after page refreshes or network
  interruptions
- **Full Unicode Support**: Displays international characters and emojis
  correctly
- **Clickable Links**: Automatically detects and makes URLs clickable
- **Copy/Paste Support**: Select text to automatically copy it to your clipboard
- **Multiple Rendering Options**: Choose between different rendering engines for
  optimal performance

<a id="accessing-the-terminal"></a>

## Access the terminal

### From the Dashboard

1. Navigate to your workspace in the Coder dashboard
2. Select the **Terminal** button or icon
3. The terminal will open in a new browser tab or window

The terminal automatically connects to your workspace agent using an optimized
WebSocket connection.

### Direct URL Access

You can also bookmark or share direct terminal URLs:

```txt
https://coder.example.com/@username/workspace-name/terminal
```

To access a specific agent in a multi-agent workspace:

```txt
https://coder.example.com/@username/workspace-name.agent-name/terminal
```

## Architecture

### How It Works

The Web Terminal creates a persistent connection between your browser and the
workspace:

1. **Browser**: Renders the terminal using xterm.js
2. **WebSocket**: Maintains a persistent, low-latency connection
3. **Control plane**: Routes traffic between browser and workspace
4. **Workspace Agent**: Manages the pseudo-terminal (PTY) session
5. **Shell Process**: Your actual bash/zsh/fish shell

The connection flow is: Browser ↔ WebSocket ↔ Control plane ↔ Workspace Agent ↔ Shell Process

### Reconnection & Persistence

The terminal uses reconnection tokens to maintain session state:

- Each terminal session has a unique UUID
- If the connection drops, the same token is used to reconnect
- The workspace agent buffers output during disconnections
- Your shell session continues running even when the browser is closed

## Customization

### Font Selection

You can customize the terminal font through your user settings:

1. Select your avatar in the top-right corner
2. Select **Settings** → **Appearance**
3. Choose from available fonts:
   - **Geist Mono** (default)
   - **IBM Plex Mono**
   - **Fira Code** (with ligatures)
   - **JetBrains Mono**
   - **Source Code Pro**

The font change applies immediately to all open terminal sessions.

### Rendering Engine

Administrators can configure the terminal renderer for performance optimization:

```yaml
# In your Coder deployment configuration
webTerminalRenderer: "canvas"  # Options: canvas, webgl, dom
```

Or via environment variable:

```sh
CODER_WEB_TERMINAL_RENDERER=canvas
```

**Renderer Options:**

- **`canvas`** (default): Best compatibility, good performance on most systems
- **`webgl`**: Hardware-accelerated, ideal for high-refresh terminals and
  complex rendering
- **`dom`**: Fallback option, useful for accessibility tools or older browsers

> **Note:** The renderer setting is deployment-wide and requires a control plane
> restart to take effect.

## Keyboard Shortcuts

The Web Terminal supports standard terminal keybindings:

| Shortcut                            | Action                    |
|-------------------------------------|---------------------------|
| `Ctrl+Shift+C` (Mac: `Cmd+Shift+C`) | Copy selected text        |
| `Ctrl+Shift+V` (Mac: `Cmd+Shift+V`) | Paste from clipboard      |
| `Shift+Enter`                       | Insert literal newline    |
| `Ctrl+C`                            | Send interrupt (SIGINT)   |
| `Ctrl+D`                            | Send EOF / exit shell     |
| `Ctrl+Z`                            | Suspend process (SIGTSTP) |

### Copy/Paste Behavior

- **Auto-copy**: Selecting text automatically copies it to your clipboard
- **Paste**: Use the standard paste shortcut or middle-click (on Linux/X11)
- **Browser permissions**: First paste may prompt for clipboard access

## URL Handling

The terminal automatically detects URLs and makes them clickable.
When you select a URL:

- **External URLs** (e.g., `https://example.com`) open in a new tab
- **Localhost URLs** (e.g., `http://localhost:3000`) are automatically
  port-forwarded through Coder's [port forwarding](./port-forwarding.md) system
- **Port-forwarded URLs** use your configured workspace proxy

This makes it seamless to open development servers running in your workspace.

## Advanced Usage

### Custom Commands

You can open a terminal with a specific command by adding a query parameter:

```txt
https://coder.example.com/@user/workspace/terminal?command=htop
```

When a `?command=` parameter is present, a confirmation dialog is shown before
the command executes. The user must select **Run command** to proceed or
**Cancel** to close the terminal window. This prevents external links from
silently executing arbitrary commands in a workspace.

Template-configured apps that use the `command` attribute in
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
are trusted and bypass the confirmation dialog. These apps use the `?app=`
parameter internally, which resolves the command from the agent's app list.

### Container Selection

For workspaces with multiple Docker containers, specify which container to
connect to:

```txt
https://coder.example.com/@user/workspace/terminal?container=sidecar
```

You can also specify the container user:

```txt
https://coder.example.com/@user/workspace/terminal?container=app&container_user=node
```

> **Note:** This feature only works with Docker containers.

### Debug Mode

Enable debug information to monitor connection latency:

```txt
https://coder.example.com/@user/workspace/terminal?debug
```

This displays the current latency to your selected workspace proxy in the
bottom-right corner.

## Configuration File Support

The Web Terminal uses xterm.js under the hood, which is configured
programmatically rather than through a configuration file. However, you can
customize various aspects:

### User-Side Customization

End-users can customize:

- **Font family** via Settings → Appearance
- **Shell environment** via dotfiles or shell rc files
- **TERM variable** is automatically set to `xterm-256color`

### Shell Configuration

The terminal respects your shell's configuration files:

```sh
# ~/.bashrc or ~/.zshrc
export PS1="\u@\h:\w\$ "  # Custom prompt
alias ll="ls -lah"         # Custom aliases

# Set terminal colors
export CTERM=xterm-256color
```

## Troubleshooting

### Connection Issues

If the terminal fails to connect:

1. **Check workspace status**: Ensure your workspace is running
2. **Verify agent health**: Look for agent connection warnings
3. **Network issues**: Check if WebSockets are blocked by your firewall/proxy
4. **Browser console**: Open DevTools to see WebSocket error messages

### Display Issues

If characters or colors appear incorrect:

1. **Unicode support**: Ensure your shell locale is set correctly (`locale -a`)
2. **Terminal type**: The terminal sets `TERM=xterm-256color` automatically
3. **Color schemes**: Some applications may not render correctly in dark mode
4. **Font rendering**: Try switching terminal fonts in your appearance settings

---

# JetBrains IDEs

Source: https://coder.com/docs/user-guides/workspace-access/jetbrains

Coder supports JetBrains IDEs using [Toolbox](https://www.jetbrains.com/toolbox/) and [Gateway](https://www.jetbrains.com/remote-development/gateway/). The following
IDEs are supported for remote development:

- IntelliJ IDEA
- CLion
- GoLand
- PyCharm
- Rider
- RubyMine
- WebStorm
- PhpStorm
- RustRover

> [!IMPORTANT]
> Remote development works with paid and non-commercial licenses of JetBrains IDEs

<children></children>

If you experience any issues, please
[create a GitHub issue](https://github.com/coder/coder/issues) or ask in
[our Discord channel](https://discord.gg/coder).

---

# JetBrains Gateway

Source: https://coder.com/docs/user-guides/workspace-access/jetbrains/gateway

## JetBrains Gateway

> [!WARNING]
> Using Coder through JetBrains Gateway is not recommended at this time. Instead, we suggest using [JetBrains Toolbox](https://coder.com/docs/user-guides/workspace-access/jetbrains/toolbox) for stability and performance benefits. If you are currently using Gateway, we recommend [migration](https://www.jetbrains.com/help/toolbox-app/jetbrains-gateway-migrations-guide.html).

JetBrains Gateway is a compact desktop app that allows you to work remotely with
a JetBrains IDE without downloading one. Visit the
[JetBrains Gateway website](https://www.jetbrains.com/remote-development/gateway/)
to learn more about Gateway.

Gateway can connect to a Coder workspace using Coder's Gateway plugin or through a
manually configured SSH connection.

### How to use the plugin

> [!NOTE]
> If you experience problems, please
> [create a GitHub issue](https://github.com/coder/coder/issues) or share in
> [our Discord channel](https://discord.gg/coder).

1. [Install Gateway](https://www.jetbrains.com/help/idea/jetbrains-gateway.html)
   and open the application.
1. Under **Install More Providers**, find the Coder icon and select **Install**
   to install the Coder plugin.
1. After Gateway installs the plugin, it will appear in the **Run the IDE
   Remotely** section.

   Select **Connect to Coder** to launch the plugin:

   ![Gateway Connect to Coder](../../../images/gateway/plugin-connect-to-coder.png)

1. Enter your Coder deployment's
   [Access Url](../../../admin/setup/index.md#access-url) and select **Connect**.

   Gateway opens your Coder deployment's `cli-auth` page with a session token.
   Select the copy button, paste the session token in the Gateway **Session
   Token** window, then select **OK**:

   ![Gateway Session Token](../../../images/gateway/plugin-session-token.png)

1. To create a new workspace:

   Select the <kbd>+</kbd> icon to open a browser and go to the templates page in
   your Coder deployment to create a workspace.

1. If a workspace already exists but is stopped, select the workspace from the
   list, then select the green arrow to start the workspace.

1. When the workspace status is **Running**, select **Select IDE and Project**:

   ![Gateway IDE List](../../../images/gateway/plugin-select-ide.png)

1. Select the JetBrains IDE for your project and the project directory then
   select **Start IDE and connect**:

   ![Gateway Select IDE](../../../images/gateway/plugin-ide-list.png)

   Gateway connects using the IDE you selected:

   ![Gateway IDE Opened](../../../images/gateway/gateway-intellij-opened.png)

   The JetBrains IDE is remotely installed into `~/.cache/JetBrains/RemoteDev/dist`.

### Update a Coder plugin version

1. Select the gear icon at the bottom left of the Gateway home screen, then
   **Settings**.

1. In the **Marketplace** tab within Plugins, enter Coder and if a newer plugin
   release is available, select **Update** then **OK**:

   ![Gateway Settings and Marketplace](../../../images/gateway/plugin-settings-marketplace.png)

<a id="configuring-the-gateway-plugin-to-use-internal-certificates"></a>

### Configure the Gateway plugin to use internal certificates

When you attempt to connect to a Coder deployment that uses internally signed
certificates, you might receive the following error in Gateway:

```console
Failed to configure connection to https://coder.internal.enterprise/: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
```

To resolve this issue, you will need to add Coder's certificate to the Java
trust store present on your local machine as well as to the Coder plugin settings.

1. Add the certificate to the Java trust store:

   <div class="tabs">

   #### Linux

   ```txt
   <Gateway installation directory>/jbr/lib/security/cacerts
   ```

   Use the `keytool` utility that ships with Java:

   ```sh
   keytool -import -alias coder -file <certificate> -keystore /path/to/trust/store
   ```

   #### macOS

   ```txt
   <Gateway installation directory>/jbr/lib/security/cacerts
   /Library/Application Support/JetBrains/Toolbox/apps/JetBrainsGateway/ch-0/<app-id>/JetBrains Gateway.app/Contents/jbr/Contents/Home/lib/security/cacerts # Path for Toolbox installation
   ```

   Use the `keytool` included in the JetBrains Gateway installation:

   ```sh
   keytool -import -alias coder -file cacert.pem -keystore /Applications/JetBrains\ Gateway.app/Contents/jbr/Contents/Home/lib/security/cacerts
   ```

   #### Windows

   ```txt
   C:\Program Files (x86)\<Gateway installation directory>\jre\lib\security\cacerts\%USERPROFILE%\AppData\Local\JetBrains\Toolbox\bin\jre\lib\security\cacerts # Path for Toolbox installation
   ```

   Use the `keytool` included in the JetBrains Gateway installation:

   ```ps1
   & 'C:\Program Files\JetBrains\JetBrains Gateway <version>/jbr/bin/keytool.exe' 'C:\Program Files\JetBrains\JetBrains Gateway <version>/jre/lib/security/cacerts' -import -alias coder -file <cert>

   # command for Toolbox installation
   & '%USERPROFILE%\AppData\Local\JetBrains\Toolbox\apps\Gateway\ch-0\<VERSION>\jbr\bin\keytool.exe' '%USERPROFILE%\AppData\Local\JetBrains\Toolbox\bin\jre\lib\security\cacerts' -import -alias coder -file <cert>
   ```

   </div>

1. In JetBrains, go to **Settings** > **Tools** > **Coder**.

1. Paste the path to the certificate in **CA Path**.

## Manually Configuring A JetBrains Gateway Connection

This is in lieu of using Coder's Gateway plugin which automatically performs these steps.

1. [Install Gateway](https://www.jetbrains.com/help/idea/jetbrains-gateway.html).

1. [Configure the `coder` CLI](../index.md#configure-ssh).

1. Open Gateway, make sure **SSH** is selected under **Remote Development**.

1. Select **New Connection**:

   ![Gateway Home](../../../images/gateway/gateway-home.png)

1. In the resulting dialog, select the gear icon to the right of **Connection**:

   ![Gateway New Connection](../../../images/gateway/gateway-new-connection.png)

1. Select <kbd>+</kbd> to add a new SSH connection:

   ![Gateway Add Connection](../../../images/gateway/gateway-add-ssh-configuration.png)

1. For the Host, enter `coder.<workspace name>`

1. For the Port, enter `22` (this is ignored by Coder)

1. For the Username, enter your workspace username.

1. For the Authentication Type, select **OpenSSH config and authentication
   agent**.

1. Make sure the checkbox for **Parse config file ~/.ssh/config** is checked.

   > [!TIP]
   > Gateway discovers hosts by parsing `~/.ssh/config`. If your workspaces
   > do not appear in Gateway's host list, re-run `coder config-ssh
   > --no-wildcard` to generate an individual `Host` entry per workspace
   > instead of a wildcard block.

1. Select **Test Connection** to validate these settings.

1. Select **OK**:

   ![Gateway SSH Configuration](../../../images/gateway/gateway-create-ssh-configuration.png)

1. Select the connection you just added:

   ![Gateway Welcome](../../../images/gateway/gateway-welcome.png)

1. Select **Check Connection and Continue**:

   ![Gateway Continue](../../../images/gateway/gateway-continue.png)

1. Select the JetBrains IDE for your project and the project directory. SSH into
   your server to create a directory or check out code if you haven't already.

   ![Gateway Choose IDE](../../../images/gateway/gateway-choose-ide.png)

   The JetBrains IDE is remotely installed into `~/.cache/JetBrains/RemoteDev/dist`

1. Select **Download and Start IDE** to connect.

   ![Gateway IDE Opened](../../../images/gateway/gateway-intellij-opened.png)

<a id="using-an-existing-jetbrains-installation-in-the-workspace"></a>

## Use an existing JetBrains installation in the workspace

You can ask your template administrator to [pre-install the JetBrains IDEs backend](../../../admin/templates/extending-templates/jetbrains-preinstall.md) in a template to make JetBrains IDE start faster on first connection.

---

# JetBrains Toolbox (Beta)

Source: https://coder.com/docs/user-guides/workspace-access/jetbrains/toolbox

JetBrains Toolbox helps you manage JetBrains products and includes remote development capabilities for connecting to Coder workspaces.

For more details, visit the [official JetBrains documentation](https://www.jetbrains.com/help/toolbox-app/manage-providers.html#shx3a8_18).

## Install the Coder provider for Toolbox

1. Install [JetBrains Toolbox](https://www.jetbrains.com/toolbox-app/) version 2.6.0.40632 or later.
1. Open the Toolbox App.
1. From the switcher drop-down, select **Manage Providers**.
1. In the **Providers** window, under the Available node, locate the **Coder** provider and select **Install**.

![Install the Coder provider in JetBrains Toolbox](../../../images/user-guides/jetbrains/toolbox/install.png)

## Connect

1. In the Toolbox App, select **Coder**.
1. Enter the URL address and select **Sign In**.
   ![JetBrains Toolbox Coder provider URL](../../../images/user-guides/jetbrains/toolbox/login-url.png)
1. Authenticate to Coder adding a token for the session and select **Connect**.
   ![JetBrains Toolbox Coder provider token](../../../images/user-guides/jetbrains/toolbox/login-token.png)
   After the authentication is completed, you are connected to your development environment and can open and work on projects.
   ![JetBrains Toolbox Coder Workspaces](../../../images/user-guides/jetbrains/toolbox/workspaces.png)

## Use URI parameters

For direct connections or creating bookmarks, use custom URI links with parameters:

```sh
jetbrains://gateway/com.coder.toolbox?url=https://coder.example.com&token=<auth-token>&workspace=my-workspace
```

Required parameters:

- `url`: Your Coder deployment URL
- `token`: Coder authentication token
- `workspace`: Name of your workspace

Optional parameters:

- `agent_id`: ID of the agent (only required if workspace has multiple agents)
- `folder`: Specific project folder path to open
- `ide_product_code`: Specific IDE product code (e.g., "IU" for IntelliJ IDEA Ultimate)
- `ide_build_number`: Specific build number of the JetBrains IDE

For more details, see the [coder-jetbrains-toolbox repository](https://github.com/coder/coder-jetbrains-toolbox#connect-to-a-coder-workspace-via-jetbrains-toolbox-uri).

## Configure internal certificates

To connect to a Coder deployment that uses internal certificates, configure the certificates directly in the Coder plugin settings in JetBrains Toolbox:

1. In the Toolbox App, select **Coder**.
1. Select the (⋮) next to the username in top right corner.
1. Select **Settings**.
1. Add your certificate path in the **CA Path** field.
   ![JetBrains Toolbox Coder Provider certificate path](../../../images/user-guides/jetbrains/toolbox/certificate.png)

## Troubleshooting

If you encounter issues connecting to your Coder workspace via JetBrains Toolbox, follow these steps to enable and capture debug logs:

### Enable Debug Logging

1. Open Toolbox
1. Navigate to the **Toolbox App Menu (hexagonal menu icon) > Settings > Advanced**.
1. In the screen that appears, select `DEBUG` for the Log level: section.
1. Hit the back button at the top.
1. Retry the same operation

### Capture Debug Logs

1. Access logs via **Toolbox App Menu > About > Show log files**.
2. Locate the log file named `jetbrains-toolbox.log` and attach it to your support ticket.
3. If you need to capture logs for a specific workspace, you can also generate a ZIP file using the Workspace action menu, available either on the main Workspaces page in Coder view or within the individual workspace view, under the option labeled **Collect logs**.

## Additional Resources

- [JetBrains Toolbox documentation](https://www.jetbrains.com/help/toolbox-app)
- [Coder JetBrains Toolbox Plugin Github](https://github.com/coder/coder-jetbrains-toolbox)

---

# Remote desktops

Source: https://coder.com/docs/user-guides/workspace-access/remote-desktops

## RDP

The most common way to get a GUI-based connection to a Windows workspace is by using Remote Desktop Protocol (RDP).

<div class="tabs">

### Desktop Client

To use RDP with Coder, you'll need to install an
[RDP client](https://docs.microsoft.com/en-us/windows-server/remote/remote-desktop-services/clients/remote-desktop-clients)
on your local machine, and enable RDP on your workspace.

<div class="tabs">

#### Coder Desktop

[Coder Desktop](../desktop/index.md)'s **Coder Connect** feature creates a connection to your workspaces in the background. Use your favorite RDP client to connect to `<workspace-name>.coder`.

You can use the [RDP Desktop](https://registry.coder.com/modules/coder/local-windows-rdp) module to add a single-click button to open an RDP session in the browser.

![RDP Desktop Button](../../images/user-guides/remote-desktops/rdp-button.gif)

You can also use a URI handler to launch an RDP session directly.

The URI format is:

```txt
coder://<your Coder server name>/v0/open/ws/<workspace name>/agent/<agent name>/rdp?username=<username>&password=<password>
```

For example:

```txt
coder://coder.example.com/v0/open/ws/myworkspace/agent/main/rdp?username=Administrator&password=coderRDP!
```

To include a Coder Desktop button on the workspace dashboard page, add a `coder_app` resource to the template:

```tf
locals {
  server_name = regex("https?:\\/\\/([^\\/]+)", data.coder_workspace.me.access_url)[0]
}

resource "coder_app" "rdp-coder-desktop" {
  agent_id     = resource.coder_agent.main.id
  slug         = "rdp-desktop"
  display_name = "RDP Desktop"
  url          = "coder://${local.server_name}/v0/open/ws/${data.coder_workspace.me.name}/agent/main/rdp?username=Administrator&password=coderRDP!"
  icon         = "/icon/desktop.svg"
  external     = true
}
```

#### CLI

Use the following command to forward the RDP port to your local machine:

```console
coder port-forward <workspace-name> --tcp 3399:3389
```

Then, connect to your workspace via RDP at `localhost:3399`.
![windows-rdp](../../images/user-guides/remote-desktops/windows_rdp_client.png)

</div>

> [!NOTE]
> Some versions of Windows, including Windows Server 2022, do not communicate correctly over UDP when using Coder Connect because they do not respect the maximum transmission unit (MTU) of the link. When this happens, the RDP client will appear to connect, but displays a blank screen.
>
> To avoid this error, Coder's [Windows RDP](https://registry.coder.com/modules/windows-rdp) module [disables RDP over UDP automatically](https://github.com/coder/registry/blob/b58bfebcf3bcdcde4f06a183f92eb3e01842d270/registry/coder/modules/windows-rdp/powershell-installation-script.tftpl#L22).
>
> To disable RDP over UDP manually, run the following in PowerShell:
>
> ```powershell
> New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services' -Name "SelectTransport" -Value 1 -PropertyType DWORD -Force
> Restart-Service -Name "TermService" -Force
> ```

### Browser

Our [RDP Web](https://registry.coder.com/modules/windows-rdp) module in the Coder Registry adds a one-click button to open an RDP session in the browser. This requires just a few lines of Terraform in your template, see the documentation on our registry for setup.

![Windows RDP Web](../../images/user-guides/remote-desktops/web-rdp-demo.png)

</div>

> [!NOTE]
> The default username is `Administrator` and the password is `coderRDP!`.

## Amazon DCV

Our [Amazon DCV Windows](https://registry.coder.com/modules/amazon-dcv-windows) installs and configures the Amazon DCV server for seamless remote desktop access. It allows connecting through the both the [Amazon DCV desktop clients](https://docs.aws.amazon.com/dcv/latest/userguide/using-connecting.html) and a [web browser](https://docs.aws.amazon.com/dcv/latest/userguide/using-connecting-browser-connect.html).

<div class="tabs">

### Desktop Client

Connect using the [Amazon DCV Desktop client](https://docs.aws.amazon.com/dcv/latest/userguide/using-connecting.html) by forwarding the DCV port to your local machine:

<div class="tabs">

#### Coder Desktop

[Coder Desktop](../desktop/index.md)'s **Coder Connect** feature creates a connection to your workspaces in the background. Use DCV client to connect to `<workspace-name>.coder:8443`.

#### CLI

Use the following command to forward the DCV port to your local machine:

```console
coder port-forward <workspace-name> --tcp 8443:8443
```

</div>

### Browser

Our [Amazon DCV Windows](https://registry.coder.com/modules/amazon-dcv-windows) module adds a one-click button to open an Amazon DCV session in the browser. This requires just a few lines of Terraform in your template, see the documentation on our registry for setup.

</div>

![Amazon DCV](../../images/user-guides/remote-desktops/amazon-dcv-windows-demo.png)

## VNC

The common way to connect to a desktop session of a Linux workspace is to use a VNC client. The VNC client can be installed on your local machine or accessed through a web browser. There is an additional requirement to install the VNC server on the workspace.

Installation instructions vary depending on your workspace's operating system, platform, and build system. Refer to the [enterprise-desktop](https://github.com/coder/images/tree/main/images/desktop) image for a starting point which can be used to provision a Dockerized workspace with the following software:

- Ubuntu 24.04
- XFCE Desktop
- KasmVNC Server and Web Client

<div class="tabs">

### Desktop Client

Use a VNC client (e.g., [TigerVNC](https://tigervnc.org/)) by forwarding the VNC port to your local machine.

<div class="tab">

#### Coder Desktop

[Coder Desktop](../desktop/index.md)'s **Coder Connect** feature allows you to connect to your workspace's VNC server at `<workspace-name>.coder:5900`.

#### CLI

Use the following command to forward the VNC port to your local machine:

```sh
coder port-forward <workspace-name> --tcp 5900:5900
```

Now you can connect to your workspace's VNC server using a VNC client at `localhost:5900`.

</div>

### Browser

The [KasmVNC module](https://registry.coder.com/modules/coder/kasmvnc) allows browser-based access to your workspace by installing and configuring the [KasmVNC](https://github.com/kasmtech/KasmVNC) server and web client.

</div>

![VNC Desktop in Coder](../../images/user-guides/remote-desktops/vnc-desktop.png)

---

# Emacs TRAMP

Source: https://coder.com/docs/user-guides/workspace-access/emacs-tramp

[Emacs TRAMP](https://www.emacswiki.org/emacs/TrampMode) is a method of running
editing operations on a remote server.

<a id="connecting-to-a-workspace"></a>

## Connect to a workspace

To connect to your workspace first run:

```sh
coder config-ssh
```

Then you can connect to your workspace by its name in the format:
`coder.<WORKSPACE NAME>`.

In Emacs type `C-x d` and then input: `/-:coder.<WORKSPACE NAME>:` and hit
enter. This will open up Dired on the workspace's home directory.

<a id="using-ssh"></a>

### Use SSH

By default Emacs TRAMP is setup to use SCP to access files on the Coder
workspace instance. However you might want to use SSH if you have a jumpbox or
some other complex network setup.

To do so set the following in your Emacs `init.el` file:

```lisp
(setq tramp-default-method "ssh")
```

Then when you access the workspace instance via `/-:coder.<WORKSPACE NAME>`
Emacs will use SSH. Setting `tramp-default-method` will also tell `ansi-term`
mode the correct way to access the remote when directory tracking.

## Directory Tracking

### ansi-term

If you run your terminal in Emacs via `ansi-term` then you might run into a
problem where while SSH-ed into a workspace Emacs will not change its
`default-directory` to open files in the directory your shell is in.

To fix this:

1. In your workspace Terraform template be sure to add the following:

   ```tf
   data "coder_workspace" "me" {
   }

   resource "coder_agent" "main" {
     # ...
     env = {
       name = "CODER_WORKSPACE_NAME"
       value = data.coder_workspace.me.name
     }
   }
   ```

2. Next in the shell profile file on the workspace (ex., `~/.bashrc` for Bash
   and `~/.zshrc` for Zsh) add the following:

   ```sh
   ansi_term_announce_host() {
       printf '\033AnSiTh %s\n' "coder.$CODER_WORKSPACE_NAME"
   }

   ansi_term_announce_user() {
       printf '\033AnSiTu %s\n' "$USER"
   }

   ansi_term_announce_pwd() {
       printf '\033AnSiTc %s\n' "$PWD"
   }

   ansi_term_announce() {
       ansi_term_announce_host
       ansi_term_announce_user
       ansi_term_announce_pwd
   }

   cd()    { command cd    "$@"; ansi_term_announce_pwd; }
   pushd() { command pushd "$@"; ansi_term_announce_pwd; }
   popd()  { command popd  "$@"; ansi_term_announce_pwd; }

   ansi_term_announce
   ```

   Ansi Term expects the terminal running inside of it to send escape codes to
   inform Emacs of the hostname, user, and working directory. The above code
   sends these escape codes and associated data whenever the terminal logs in
   and whenever the directory changes.

### eshell

The `eshell` mode will perform directory tracking by default, no additional
configuration is needed.

## Language Servers (Code Completion)

If you use [`lsp-mode`](https://emacs-lsp.github.io/lsp-mode) for code
intelligence and completion some additional configuration is required.

In your Emacs `init.el` file you must register a LSP client and tell `lsp-mode`
how to find it on the remote machine using the `lsp-register-client` function.
For each LSP server you want to use in your workspace add the following:

```lisp
(lsp-register-client (make-lsp-client :new-connection (lsp-tramp-connection "<LSP SERVER BINARY>")
              :major-modes '(<LANGUAGE MODE>)
              :remote? t
              :server-id '<LANGUAGE SERVER ID>))
```

This tells `lsp-mode` to look for a language server binary named
`<LSP SERVER BINARY>` for use in `<LANGUAGE MODE>` on a machine named
`coder.<WORKSPACE NAME>`. Be sure to replace the values between angle brackets:

- `<LSP SERVER BINARY>` : The name of the language server binary, without any
  path components. For example to use the Deno Javascript language server use
  the value `deno`.
- `<LANGUAGE MODE>`: The name of the Emacs major mode for which the language
  server should be used. For example to enable the language server for
  Javascript development use the value `web-mode`.
- `<LANGUAGE SERVER ID>`: This is just the name that `lsp-mode` will use to
  refer to this language server. If you are ever looking for output buffers or
  files they may have this name in them.

Calling the `lsp-register-client` function will tell `lsp-mode` the name of the
LSP server binary. However this binary must be accessible via the path. If the
language server binary is not in the path you must modify `tramp-remote-path` so
that `lsp-mode` knows in what directories to look for the LSP server. To do this
use TRAMP's connection profiles functionality. These connection profiles let you
customize variables depending on what machine you are connected to. Add the
following to your `init.el`:

```lisp
(connection-local-set-profile-variables 'remote-path-lsp-servers
                                 '((tramp-remote-path . ("<PATH TO ADD>" tramp-default-remote-path))))
(connection-local-set-profiles '(:machine "coder.<WORKSPACE NAME>") 'remote-path-lsp-servers)
```

The `connection-local-set-profile-variables` function creates a new connection
profile by the name `remote-path-lsp-servers`. The
`connection-local-set-profiles` then indicates this `remote-path-lsp-servers`
connection profile should be used when connecting to a server named
`coder.<WORKSPACE NAME>`. Be sure to replace `<PATH TO ADD>` with the directory
in which a LSP server is present.

TRAMP and `lsp-mode` are fickle friends, sometimes there is weird behavior. If
you find that language servers are hanging in the `starting` state then
[it might be helpful](https://github.com/emacs-lsp/lsp-mode/issues/2709#issuecomment-800868919)
to set the `lsp-log-io` variable to `t`.

More details on configuring `lsp-mode` for TRAMP can be found
[in the `lsp-mode` documentation](https://emacs-lsp.github.io/lsp-mode/page/remote/).
The
[TRAMP `tramp-remote-path` documentation](https://www.gnu.org/software/emacs/manual/html_node/tramp/Remote-programs.html#Remote-programs)
contains more examples and details of connection profiles.

---

# Workspace ports

Source: https://coder.com/docs/user-guides/workspace-access/port-forwarding

## Port forwarding

Port forwarding lets developers securely access processes on their Coder
workspace from a local machine. A common use case is testing web applications in
a browser.

There are multiple ways to forward ports in Coder:

| Method                                                          | Details                                                                                                                                                                 |
|:----------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Coder Desktop](#coder-desktop)                                 | Uses a VPN tunnel to your workspaces and provides access to all running ports. Supports peer-to-peer connections for the best performance.                              |
| [`coder port-forward` command](#the-coder-port-forward-command) | Can be used to forward specific TCP or UDP ports from the remote workspace so they can be accessed locally. Supports peer-to-peer connections for the best performance. |
| [Dashboard](#dashboard)                                         | Proxies traffic through the Coder control plane.                                                                                                                        |
| [SSH](#ssh)                                                     | Forwards ports over an SSH connection.                                                                                                                                  |

## Coder Desktop

> [!TIP]
> Coder Desktop is the recommended way to access workspace ports. It provides automatic port forwarding with no manual setup.

[Coder Desktop](../desktop/index.md) creates a VPN tunnel that automatically forwards every port in your workspace. Any service listening on a port is instantly accessible at `<workspace-name>.coder:PORT` from your local machine, with no additional commands or configuration.

This is the simplest option for most developers: install Coder Desktop, enable Coder Connect, and all ports just work. Connections are peer-to-peer for the best performance.

## The `coder port-forward` command

This command can be used to forward TCP or UDP ports from the remote workspace
so they can be accessed locally. Both the TCP and UDP command line flags
(`--tcp` and `--udp`) can be given once or multiple times.

The supported syntax variations for the `--tcp` and `--udp` flag are:

- Single port with optional remote port: `local_port[:remote_port]`
- Comma separation `local_port1,local_port2`
- Port ranges `start_port-end_port`
- Any combination of the above

### Examples

Forward the remote TCP port `8080` to local port `8000`:

```console
coder port-forward myworkspace --tcp 8000:8080
```

Forward the remote TCP port `3000` and all ports from `9990` to `9999` to their
respective local ports.

```console
coder port-forward myworkspace --tcp 3000,9990-9999
```

For more examples, see `coder port-forward --help`.

## Dashboard

To enable port forwarding via the dashboard, Coder must be configured with a
[wildcard access URL](../../admin/setup/index.md#wildcard-access-url). If an
access URL is not specified, Coder will create
[a publicly accessible URL](../../admin/setup/index.md#tunnel) to reverse
proxy the deployment, and port forwarding will work.

There is a
[DNS limitation](https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1)
where each segment of hostnames must not exceed 63 characters. If your app
name, agent name, workspace name and username exceed 63 characters in the
hostname, port forwarding via the dashboard will not work.

### From a coder_app resource

One way to port forward is to configure a `coder_app` resource in the
workspace's template. This approach shows a visual application icon in the
dashboard. See the following `coder_app` example for a Node React app and note
the `subdomain` and `share` settings:

```tf
# node app
resource "coder_app" "node-react-app" {
  agent_id  = coder_agent.dev.id
  slug      = "node-react-app"
  icon      = "https://upload.wikimedia.org/wikipedia/commons/a/a7/React-icon.svg"
  url       = "http://localhost:3000"
  subdomain = true
  share     = "authenticated"

  healthcheck {
    url       = "http://localhost:3000/healthz"
    interval  = 10
    threshold = 30
  }

}
```

Valid `share` values include `owner` - private to the user, `authenticated` -
accessible by any user authenticated to the Coder deployment, and `public` -
accessible by users outside of the Coder deployment.

![Port forwarding from an app in the UI](../../images/networking/portforwarddashboard.png)

<a id="accessing-workspace-ports"></a>

## Access workspace ports

Another way to port forward in the dashboard is to use the "Open Ports" button
to specify an arbitrary port. Coder will also detect if apps inside the
workspace are listening on ports, and list them below the port input (this is
only supported on Windows and Linux workspace agents).

![Port forwarding in the UI](../../images/networking/listeningports.png)

<a id="sharing-ports"></a>

### Share ports

You can share ports as URLs, either with other authenticated coder users or
publicly. Using the open ports interface, you can assign a sharing levels that
match our `coder_app`’s share option in
[Coder terraform provider](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app#share).

- `owner` (Default): The implicit sharing level for all listening ports, only
  visible to the workspace owner
- `organization`: Accessible by authenticated users in the same organization as
  the workspace.
- `authenticated`: Accessible by other authenticated Coder users on the same
  deployment.
- `public`: Accessible by any user with the associated URL.

Once a port is shared at either `authenticated` or `public` levels, it will stay
pinned in the open ports UI for better visibility regardless of whether or not
it is still accessible.

![Annotated port controls in the UI](../../images/networking/annotatedports.png)

> [!NOTE]
> The sharing level is limited by the maximum level enforced in the template
> settings in licensed deployments, and not restricted in OSS deployments.

This can also be used to change the sharing level of port-based `coder_app`s by
entering their port number in the sharable ports UI. The `share` attribute on
`coder_app` resource uses a different method of authentication and **is not
impacted by the template's maximum sharing level**, nor the level of a shared
port that points to the app.

<a id="configuring-port-protocol"></a>

### Configure port protocol

Both listening and shared ports can be configured to use either `HTTP` or
`HTTPS` to connect to the port. For listening ports the protocol selector
applies to any port you input or select from the menu. Shared ports have
protocol configuration for each shared port individually.

You can also access any port on the workspace and can configure the port
protocol manually by appending a `s` to the port in the URL.

```console
# Uses HTTP
https://33295--agent--workspace--user--apps.example.com/
# Uses HTTPS
https://33295s--agent--workspace--user--apps.example.com/
```

## SSH

First, [configure SSH](./index.md#configure-ssh) on your local machine. Then,
use `ssh` to forward like so:

```console
ssh -L 8080:localhost:8000 coder.myworkspace
```

You can read more on SSH port forwarding
[here](https://www.ssh.com/academy/ssh/tunneling/example).

---

# File Browser

Source: https://coder.com/docs/user-guides/workspace-access/filebrowser

File Browser is a file manager for the web that can be used to upload, download,
and view files in your workspace. A template administrator can add it by
following the
[Extending Templates](../../admin/templates/extending-templates/web-ides.md#file-browser)
guide. ![File Browser](../../images/file-browser.png)

---

# Web IDEs

Source: https://coder.com/docs/user-guides/workspace-access/web-ides

By default, Coder workspaces allow connections via:

- Web terminal
- [SSH](./index.md#ssh)

It's common to also connect via web IDEs for uses cases like zero trust
networks, data science, contractors, and infrequent code contributors.

![Row of IDEs](../../images/ide-row.png)

In Coder, web IDEs are defined as
[coder_app](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
resources in the template. With our generic model, any web application can be
used as a Coder application. For example:

To learn more about configuring IDEs in templates, see our docs on
[template administration](../../admin/templates/index.md).

![External URLs](../../images/external-apps.png)

## code-server

[`code-server`](https://github.com/coder/code-server) is our supported method of
running VS Code in the web browser. You can read more in our
[documentation for code-server](https://coder.com/docs/code-server).

![code-server in a workspace](../../images/code-server-ide.png)

## VS Code Web

We also support Microsoft's official product for using VS Code in the browser. A
template administrator can add it by following the
[Extending Templates](../../admin/templates/extending-templates/web-ides.md#vs-code-web)
guide.

![VS Code Web in Coder](../../images/vscode-web.gif)

## Jupyter Notebook

Jupyter Notebook is a web-based interactive computing platform. A template
administrator can add it by following the
[Extending Templates](../../admin/templates/extending-templates/web-ides.md#jupyter-notebook)
guide.

![Jupyter Notebook in Coder](../../images/jupyter-notebook.png)

## JupyterLab

In addition to Jupyter Notebook, you can use Jupyter lab in your workspace. A
template administrator can add it by following the
[Extending Templates](../../admin/templates/extending-templates/web-ides.md#jupyterlab)
guide.

![JupyterLab in Coder](../../images/jupyter.png)

## RStudio

RStudio is a popular IDE for R programming language. A template administrator
can add it to your workspace by following the
[Extending Templates](../../admin/templates/extending-templates/web-ides.md#rstudio)
guide.

![RStudio in Coder](../../images/rstudio-port-forward.png)

## Airflow

Apache Airflow is an open-source workflow management platform for data
engineering pipelines. A template administrator can add it by following the
[Extending Templates](../../admin/templates/extending-templates/web-ides.md#airflow)
guide.

![Airflow in Coder](../../images/airflow-port-forward.png)

## SSH Fallback

If you prefer to run web IDEs in localhost, you can port forward using
[SSH](./index.md#ssh) or the Coder CLI `port-forward` sub-command. Some web IDEs
may not support URL base path adjustment so port forwarding is the only
approach.

---

# code-server

Source: https://coder.com/docs/user-guides/workspace-access/code-server

[code-server](https://github.com/coder/code-server) is our supported method of running VS Code in the web browser.

![code-server in a workspace](../../images/code-server-ide.png)

## Differences between code-server and VS Code Web

Some of the key differences between code-server and VS Code Web are:

| Feature                  | code-server                                                                 | VS Code Web                                                       |
|--------------------------|-----------------------------------------------------------------------------|-------------------------------------------------------------------|
| Authentication           | Optional login form                                                         | No built-in auth                                                  |
| Built-in proxy           | Includes development proxy (not needed with Coder)                          | No built-in development proxy                                     |
| Clipboard integration    | Supports piping text from terminal (similar to `xclip`)                     | More limited                                                      |
| Display languages        | Supports language pack extensions                                           | Limited language support                                          |
| File operations          | Options to disable downloads and uploads                                    | No built-in restrictions                                          |
| Health endpoint          | Provides `/healthz` endpoint                                                | Limited health monitoring                                         |
| Marketplace              | Open VSX by default, configurable via flags/env vars                        | Uses Microsoft marketplace; modify `product.json` to use your own |
| Path-based routing       | Has fixes for state collisions when used path-based                         | May have issues with path-based routing in certain configurations |
| Proposed API             | Always enabled for all extensions                                           | Only Microsoft extensions without configuration                   |
| Proxy integration        | Integrates with Coder's proxy for ports panel                               | Integration is more limited                                       |
| Sourcemaps               | Loads locally                                                               | Uses CDN                                                          |
| Telemetry                | Configurable endpoint                                                       | Does not allow a configurable endpoint                            |
| Terminal access to files | You can use a terminal outside of the integrated one to interact with files | Limited to integrated terminal access                             |
| User settings            | Stored on remote disk                                                       | Stored in browser                                                 |
| Web views                | Self-contained                                                              | Uses Microsoft CDN                                                |

For more information about code-server, visit the [code-server FAQ](https://coder.com/docs/code-server/FAQ).

---

# Zed

Source: https://coder.com/docs/user-guides/workspace-access/zed

[Zed](https://zed.dev/) is an [open-source](https://github.com/zed-industries/zed)
multiplayer code editor from the creators of Atom and Tree-sitter.

## Use Zed to connect to Coder via SSH

Use the Coder CLI to log in and configure SSH, then connect to your workspace with Zed:

1. [Install Zed](https://zed.dev/docs/)
1. Install Coder CLI:

   <!-- copied from docs/install/cli.md - make changes there -->

   <div class="tabs">

   ### Linux/macOS

   Our install script is the fastest way to install Coder on Linux/macOS:

   ```sh
   curl -fsSL https://coder.com/install.sh | sh
   ```

   Refer to [GitHub releases](https://github.com/coder/coder/releases) for
   alternate installation methods (e.g. standalone binaries, system packages).

   ### Windows

   Use [GitHub releases](https://github.com/coder/coder/releases) to download the
   Windows installer (`.msi`) or standalone binary (`.exe`).

   ![Windows setup wizard](../../images/install/windows-installer.png)

   Alternatively, you can use the
   [`winget`](https://learn.microsoft.com/en-us/windows/package-manager/winget/#use-winget)
   package manager to install Coder:

   ```ps1
   winget install Coder.Coder
   ```

   </div>

   Consult the [Coder CLI documentation](../../install/cli.md) for more options.

1. Log in to your Coder deployment and authenticate when prompted:

   ```sh
   coder login coder.example.com
   ```

1. Configure Coder SSH:

   ```sh
   coder config-ssh
   ```

1. Connect to the workspace via SSH:

   ```sh
   zed ssh://coder.workspace-name
   ```

   Or use Zed's [Remote Development](https://zed.dev/docs/remote-development#setup) to connect to the workspace:

   ![Zed open remote project](../../images/zed/zed-ssh-open-remote.png)

> [!NOTE]
> If you have any suggestions or experience any issues, please
> [create a GitHub issue](https://github.com/coder/coder/issues) or share in
> [our Discord channel](https://discord.gg/coder).

---

# Cursor

Source: https://coder.com/docs/user-guides/workspace-access/cursor

[Cursor](https://cursor.sh/) is a modern IDE built on top of VS Code with enhanced AI capabilities.

Follow this guide to use Cursor to access your Coder workspaces.

If your team uses Cursor regularly, ask your Coder administrator to add a [Cursor module](https://registry.coder.com/modules/cursor) to your template.

## Install Cursor

Cursor can connect to a Coder workspace using the Coder extension:

1. [Install Cursor](https://docs.cursor.com/get-started/installation) on your local machine.

1. Open Cursor and log in or [create a Cursor account](https://authenticator.cursor.sh/sign-up)
   if you don't have one already.

## Install the Coder extension

1. You can install the Coder extension through the Marketplace built in to Cursor or manually.

   <div class="tabs">

   ## Extension Marketplace

   1. Search for Coder from the Extensions Pane and select **Install**.

   1. Coder Remote uses the **Remote - SSH extension** to connect.

      You can find it in the **Extension Pack** tab of the Coder extension.

   ## Manually

   1. Download the [latest vscode-coder extension](https://github.com/coder/vscode-coder/releases/latest) `.vsix` file.

   1. Drag the `.vsix` file into the extensions pane of Cursor.

      Alternatively:

      1. Open the Command Palette
   (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> or <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>)
   and search for `vsix`.

      1. Select **Extensions: Install from VSIX** and select the vscode-coder extension you downloaded.

   </div>

1. Coder Remote uses the **Remote - SSH extension** to connect.

   You can find it in the **Extension Pack** tab of the Coder extension.

## Open a workspace in Cursor

1. From the Cursor Command Palette
(<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> or <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>),
enter `coder` and select **Coder: Login**.

1. Follow the prompts to login and copy your session token.

   Paste the session token in the **Paste your API key** box in Cursor.

1. Select **Open Workspace** or use the Command Palette to run **Coder: Open Workspace**.

---

# Devin Desktop

Source: https://coder.com/docs/user-guides/workspace-access/devin-desktop

[Devin Desktop](https://devin.ai/desktop) is Cognition's AI-powered code editor designed for AI-assisted development.
Cognition, the maker of the Devin autonomous coding agent, rebranded the Windsurf Editor (formerly Codeium) as Devin Desktop on June 2, 2026.
If you installed Windsurf before that date, it updated to Devin Desktop automatically, and your plan, extensions, and settings were carried over.

Follow this guide to use Devin Desktop to access your Coder workspaces.

If your team uses Devin Desktop regularly, ask your Coder administrator to add Devin Desktop as a workspace application in your template.
You can also use the [devin-desktop module](https://registry.coder.com/modules/coder/devin-desktop) to easily add Devin Desktop to your Coder templates.

## Install Devin Desktop

Devin Desktop can connect to your Coder workspaces via SSH:

1. [Install Devin Desktop](https://docs.devin.ai/desktop/install) on your local machine.

1. Open Devin Desktop and select **Get started**.

   Import your settings from another IDE, or select **Start fresh**.

1. Complete the setup flow and [log in to Devin](https://app.devin.ai/auth/login) or [create a Devin account](https://app.devin.ai/auth/signup) if you don't have one already.

## Install the Coder extension

![Coder extension in Devin Desktop](../../images/user-guides/ides/windsurf-coder-extension.png)

1. You can install the Coder extension through the Marketplace built in to Devin Desktop or manually.

   <div class="tabs">

   ## Extension Marketplace

   Search for Coder from the Extensions Pane and select **Install**.

   ## Manually

   1. Download the [latest vscode-coder extension](https://github.com/coder/vscode-coder/releases/latest) `.vsix` file.

   1. Drag the `.vsix` file into the extensions pane of Devin Desktop.

      Alternatively:

      1. Open the Command Palette
         (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> or <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>) and search for `vsix`.

      1. Select **Extensions: Install from VSIX** and select the vscode-coder extension you downloaded.

   </div>

## Open a workspace in Devin Desktop

1. From the Devin Desktop Command Palette (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> or <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>),
   enter `coder` and select **Coder: Login**.

1. Follow the prompts to login and copy your session token.

   Paste the session token in the **Coder API Key** dialogue in Devin Desktop.

1. Devin Desktop prompts you to open a workspace, or you can use the Command Palette to run **Coder: Open Workspace**.

---

# Antigravity

Source: https://coder.com/docs/user-guides/workspace-access/antigravity

[Antigravity](https://antigravity.google/) is Google's desktop IDE.

Follow this guide to use Antigravity to access your Coder workspaces.

If your team uses Antigravity regularly, ask your Coder administrator to add Antigravity as a workspace application in your template.
You can also use the [Antigravity module](https://registry.coder.com/modules/coder/antigravity) to easily add Antigravity to your Coder templates.

## Install Antigravity

Antigravity connects to your Coder workspaces using the Coder extension:

1. [Install Antigravity](https://antigravity.google/) on your local machine.

1. Open Antigravity and sign in with your Google account.

## Install the Coder extension

1. You can install the Coder extension through the Marketplace built in to Antigravity or manually.

   <div class="tabs">

   ## Extension Marketplace

   Search for Coder from the Extensions Pane and select **Install**.

   ## Manually

   1. Download the [latest vscode-coder extension](https://github.com/coder/vscode-coder/releases/latest) `.vsix` file.

   1. Drag the `.vsix` file into the extensions pane of Antigravity.

      Alternatively:

      1. Open the Command Palette
         (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> or <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>) and search for `vsix`.

      1. Select **Extensions: Install from VSIX** and select the vscode-coder extension you downloaded.

   </div>

## Open a workspace in Antigravity

1. From the Antigravity Command Palette (<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> or <kbd>Cmd</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>),
   enter `coder` and select **Coder: Login**.

1. Follow the prompts to login and copy your session token.

   Paste the session token in the **Coder API Key** dialogue in Antigravity.

1. Antigravity prompts you to open a workspace, or you can use the Command Palette to run **Coder: Open Workspace**.

## Template configuration

Your Coder administrator can add Antigravity as a one-click workspace app using
the [Antigravity module](https://registry.coder.com/modules/coder/antigravity)
from the Coder registry:

```tf
module "antigravity" {
  count    = data.coder_workspace.me.start_count
  source   = "registry.coder.com/coder/antigravity/coder"
  version  = "1.0.0"
  agent_id = coder_agent.example.id
  folder   = "/home/coder/project"
}
```

---

# Coder Desktop

Source: https://coder.com/docs/user-guides/desktop

Coder Desktop provides seamless access to your remote workspaces through a native application. Connect to workspace services using simple hostnames like `myworkspace.coder`, launch applications with one click, and synchronize files between local and remote environments, all without installing a CLI or configuring manual port forwarding.

> [!TIP]
> Coder Desktop provides **automatic port forwarding** to every service running in your workspace. Any port your application listens on is instantly accessible at `workspace-name.coder:PORT` with no manual setup required. For a comparison of all port forwarding methods, see [Workspace Ports](../workspace-access/port-forwarding.md).

## What You'll Need

- A Coder deployment running `v2.20.0` or [later](https://github.com/coder/coder/releases/latest)
- Administrator privileges on your local machine (for VPN extension installation)
- Access to your Coder deployment URL

## Quick Start

1. Install: `brew install --cask coder/coder/coder-desktop` (macOS) or `winget install Coder.CoderDesktop` (Windows)
1. Open Coder Desktop and approve any system prompts to complete the installation.
1. Sign in with your deployment URL and session token
1. Enable "Coder Connect" toggle
1. Access workspaces at `workspace-name.coder`

## How It Works

**Coder Connect**, the primary component of Coder Desktop, creates a secure tunnel to your Coder deployment, allowing you to:

- **Access workspaces directly**: Connect via `workspace-name.coder` hostnames
- **Automatic port forwarding**: All workspace ports are available at `workspace-name.coder:PORT` with no configuration
- **Use any application**: SSH clients, browsers, IDEs work seamlessly
- **Sync files**: Bidirectional sync between local and remote directories
- **Work offline**: Edit files locally, sync when reconnected

The VPN extension routes only Coder traffic—your other internet activity remains unchanged.

## Installation

<div class="tabs">

### macOS

<div class="tabs">

#### Homebrew (Recommended)

```sh
brew install --cask coder/coder/coder-desktop
```

#### Manual Installation

1. Download the latest release from [coder-desktop-macos releases](https://github.com/coder/coder-desktop-macos/releases)
1. Run `Coder-Desktop.pkg` and follow the prompts to install
1. `Coder Desktop.app` will be installed to your Applications folder

</div>

Coder Desktop requires VPN extension permissions:

1. When prompted with **"Coder Desktop" would like to use a new network extension**, select **Open System Settings**
1. In **Network Extensions** settings, enable the Coder Desktop extension
1. You may need to enter your password to authorize the extension

✅ **Verify Installation**: Coder Desktop should appear in your menu bar

### Windows

<div class="tabs">

#### WinGet (Recommended)

```sh
winget install Coder.CoderDesktop
```

#### Manual Installation

1. Download the latest `CoderDesktop` installer (`.exe`) from [coder-desktop-windows releases](https://github.com/coder/coder-desktop-windows/releases)
1. Choose the correct architecture (`x64` or `arm64`) for your system
1. Run the installer and accept the license terms
1. If prompted, install the .NET Windows Desktop Runtime
1. Install Windows App Runtime SDK if prompted

</div>

- [.NET Windows Desktop Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) (installed automatically if not present)
- Windows App Runtime SDK (may require manual installation)

✅ **Verify Installation**: Coder Desktop should appear in your system tray (you may need to select **^** to show hidden icons)

</div>

<a id="testing-your-connection"></a>

## Test your connection

Once connected, test access to your workspaces:

<div class="tabs">

### SSH Connection

```sh
ssh your-workspace.coder
```

### Ping Test

```sh
# macOS
ping6 -c 3 your-workspace.coder

# Windows
ping -n 3 your-workspace.coder
```

### Web Services

Open `http://your-workspace.coder:PORT` in your browser, replacing `PORT` with the specific service port you want to access (e.g. 3000 for frontend, 8080 for API)

</div>

## Administrator Configuration

Organizations that manage Coder Desktop deployments can configure the application using MDM (Mobile Device Management) or group policy.

### Disable Automatic Updates

Administrators can disable the built-in auto-updater to manage updates through their own software distribution system.

<div class="tabs">

### macOS

Set the `disableUpdater` preference to `true` using the `defaults` command:

```sh
defaults write com.coder.Coder-Desktop disableUpdater -bool true
```

Organization administrators can also enforce this setting across managed devices using MDM (Mobile Device Management) software by deploying a configuration profile that sets this preference.

### Windows

Set the `Updater:Enable` registry value to `0` under `HKEY_LOCAL_MACHINE\SOFTWARE\Coder Desktop\App`:

```ps1
New-Item -Path "HKLM:\SOFTWARE\Coder Desktop\App" -Force
New-ItemProperty -Path "HKLM:\SOFTWARE\Coder Desktop\App" -Name "Updater:Enable" -Value 0 -PropertyType DWord -Force
```

You can also configure a `Updater:ForcedChannel` string value to lock users to a specific update channel (e.g. `stable`).

> [!NOTE]
> For security, updater settings can only be configured at the machine level (`HKLM`), not per-user (`HKCU`).

</div>

## Troubleshooting

### Connection Issues

#### Can't connect to workspace

- Verify Coder Connect is enabled (toggle should be ON)
- Check that your deployment URL is correct
- Ensure your session token hasn't expired
- Try disconnecting and reconnecting Coder Connect

#### VPN extension not working

- Restart Coder Desktop
- Check system permissions for network extensions
- Ensure only one copy of Coder Desktop is installed

### Recover from a stale tunnel

If the menu bar or tray shows **Coder Connect** as enabled but workspaces are
unreachable (SSH hangs, `workspace.coder` fails to resolve, or file sync cannot
list the workspace directory), the embedded tunnel may be in a stale state.
Restart the helper components first.
If that doesn't resolve the issue, reboot your computer.

<div class="tabs">

#### macOS

Run the following commands in a terminal.
These steps leave the app and helper daemon installed.
They only restart the running tunnel and flush DNS caches.

1. Stop the Coder VPN configuration:

    ```shell
    vpn_name=$(scutil --nc list | grep "com.coder.Coder-Desktop" | awk -F'"' '{print $2}' | tail -n1)
    if [ -n "$vpn_name" ]; then scutil --nc stop "$vpn_name"; fi
    ```

2. Quit the Coder Desktop app:

    ```shell
    osascript -e 'tell application id "com.coder.Coder-Desktop" to quit'
    ```

3. Restart the helper daemon in place:

    ```shell
    sudo launchctl kickstart -k system/com.coder.Coder-Desktop.Helper
    ```

    > [!WARNING]
    > Do not use `launchctl bootout` here. `bootout` removes the daemon from
    > launchd's system domain entirely, and relaunching the app does not
    > re-bootstrap it. Use `kickstart -k` to restart it in place.

4. Flush DNS caches:

    ```shell
    sudo dscacheutil -flushcache
    sudo killall -HUP mDNSResponder
    ```

5. Confirm the stale tunnel is gone (the command should print nothing):

    ```shell
    scutil --nc list | grep "com.coder.Coder-Desktop"
    ```

6. Relaunch **Coder Desktop** from your `/Applications` folder and toggle **Coder Connect** back on.

To verify the tunnel is healthy after relaunching, query the built-in sentinel
hostname against Coder Desktop's embedded DNS server:

```shell
dig @fd60:627a:a42b::53 AAAA is.coder--connect--enabled--right--now.coder +short
dscacheutil -q host -a name is.coder--connect--enabled--right--now.coder
```

Both commands should return an `fd60:627a:a42b::/48` address.
If `dig` returns nothing or `dscacheutil` reports no entries, Coder Connect is not publishing DNS.
[Collect logs](#collect-logs) and file an issue.

#### Windows

Run the following in an **elevated PowerShell** session.
The service restart clears the embedded DNS state.
The NRPT and adapter checks confirm the system routing policy is intact.

1. Stop the app and the VPN service:

    ```ps1
    Get-Process -Name "Coder Desktop" -ErrorAction SilentlyContinue | Stop-Process -Force
    Stop-Service -Name "Coder Desktop" -Force
    ```

2. Flush DNS caches:

    ```ps1
    ipconfig /flushdns
    Clear-DnsClientCache
    ```

3. Start the service again and relaunch the app:

    ```ps1
    Start-Service -Name "Coder Desktop"
    Start-Process "C:\Program Files\Coder Desktop\CoderDesktop.exe"
    ```

4. After re-enabling Coder Connect in the tray, verify the NRPT rule and the Wintun adapter exist:

    ```ps1
    Get-DnsClientNrptRule | Where-Object { $_.Namespace -like "*.coder" }
    Get-NetAdapter | Where-Object { $_.InterfaceDescription -like "*Wintun*" }
    ```

    If either command returns nothing while Coder Connect shows as enabled,
    the tunnel did not finish coming up. Disable and re-enable the toggle, or
    repeat the steps above.

> [!NOTE]
> `ipconfig /flushdns` does not reset Coder Desktop's embedded DNS resolver;
> restarting the service is what clears its internal cache. If you are running
> a network filtering agent (for example, Zscaler), it may shadow `.coder`
> lookups even after the tunnel comes back. Check with your IT team if DNS
> still fails after a clean restart.

</div>

### Collect logs

When reporting an issue, attach the relevant log files so we can diagnose it faster.

<div class="tabs">

#### macOS

Coder Desktop and its network extension write to the Apple [unified logging system](https://developer.apple.com/documentation/os/logging). The file sync (Mutagen) daemon writes to a separate log file.

1. Export the unified logs for the last hour with the `log` command:

    ```sh
    log show --predicate 'subsystem BEGINSWITH "com.coder.Coder-Desktop"' \
      --info --debug --last 1h > ~/Desktop/coder-desktop.log
    ```

    The `BEGINSWITH` predicate captures the app, the helper daemon, and the
    network extension, which all log under subsystems prefixed with
    `com.coder.Coder-Desktop`. Adjust `--last` (e.g. `30m`, `2h`, `1d`) to
    cover the time the issue occurred.

    You can stream the logs live while reproducing an issue:

    ```shell
    log stream --predicate 'subsystem BEGINSWITH "com.coder.Coder-Desktop"' --info --debug
    ```

    You can also view the same logs interactively in **Console.app** by
    filtering on `subsystem:com.coder.Coder-Desktop` with Info and Debug
    messages enabled.

2. If you're using file sync, also collect the Mutagen daemon log:

    ```sh
    ~/Library/Application\ Support/Coder\ Desktop/Mutagen/daemon.log
    ```

    Coder Desktop also opens this file in Console automatically when the file sync daemon fails.

#### Windows

Coder Desktop has three components that write logs: the app (UI), the VPN service, and the file sync (Mutagen) daemon.

1. App log (daily rolling):

    ```ps1
    %LOCALAPPDATA%\CoderDesktop\app.log
    ```

2. VPN service log (default install path):

    ```ps1
    C:\Program Files\Coder Desktop\coder-desktop-service.log
    ```

3. File sync (Mutagen) daemon log, if you use file sync:

    ```ps1
    %LOCALAPPDATA%\CoderDesktop\mutagen\daemon.log
    ```

You can quickly open the app log directory by pasting `%LOCALAPPDATA%\CoderDesktop` into File Explorer.

</div>

> [!TIP]
> Before attaching logs to a public issue, review them for any sensitive information (deployment URLs, usernames, hostnames) and redact as needed.

<a id="getting-help"></a>

### Get help

If you encounter issues not covered here:

- **File an issue**: [macOS](https://github.com/coder/coder-desktop-macos/issues) | [Windows](https://github.com/coder/coder-desktop-windows/issues) | [General](https://github.com/coder/coder/issues)
- **Community support**: [Discord](https://coder.com/chat)

<a id="uninstalling"></a>

## Uninstall Coder Desktop

<div class="tabs">

### macOS

1. **Disable Coder Connect** in the app menu
2. **Quit Coder Desktop** completely
3. **Remove VPN extension** from System Settings > Network Extensions
4. **Delete the app** from Applications folder
5. **Remove configuration** (optional): `rm -rf ~/Library/Application\ Support/Coder\ Desktop`

### Windows

1. **Disable Coder Connect** in the app menu
2. **Quit Coder Desktop** from system tray
3. **Uninstall** via Settings > Apps or Control Panel
4. **Remove configuration** (optional): Delete `%APPDATA%\Coder Desktop`

</div>

## Next Steps

- [Using Coder Connect and File Sync](./desktop-connect-sync.md)
- [Compare port forwarding methods](../workspace-access/port-forwarding.md)

---

# Coder Desktop Connect and Sync

Source: https://coder.com/docs/user-guides/desktop/desktop-connect-sync

Use Coder Desktop to work on your workspaces and files as though they're on your LAN.

> [!NOTE]
> Coder Desktop requires a Coder deployment running [v2.20.0](https://github.com/coder/coder/releases/tag/v2.20.0) or later.

## Coder Connect

While active, Coder Connect will list the workspaces you own and will configure your system to connect to them over private IPv6 addresses and custom hostnames ending in `.coder`.

![Coder Desktop list of workspaces](../../images/user-guides/desktop/coder-desktop-workspaces.png)

To copy the `.coder` hostname of a workspace agent, select the copy icon beside it.

You can also connect to the SSH server in your workspace using any SSH client, such as OpenSSH or PuTTY:

   ```sh
   ssh your-workspace.coder
   ```

### Automatic port forwarding

Any services listening on ports in your workspace are automatically available on the same hostname, with no manual port forwarding required. For example, you can access a web server on port `8080` by visiting `http://your-workspace.coder:8080` in your browser.

This works for all TCP ports. Start a service in your workspace and access it immediately from your local machine at `http://your-workspace.coder:PORT`.

For other port forwarding methods (CLI, dashboard, SSH), see [Workspace Ports](../workspace-access/port-forwarding.md).

> [!NOTE]
> For Coder versions v2.21.3 and earlier: the Coder IDE extensions for VSCode and JetBrains create their own tunnel and do not utilize the Coder Connect tunnel to connect to workspaces.

### Ping your workspace

<div class="tabs">

### macOS

Use `ping6` in your terminal to verify the connection to your workspace:

   ```sh
   ping6 -c 5 your-workspace.coder
   ```

### Windows

Use `ping` in a Command Prompt or PowerShell terminal to verify the connection to your workspace:

   ```sh
   ping -n 5 your-workspace.coder
   ```

</div>

## Sync a local directory with your workspace

Coder Desktop file sync provides bidirectional synchronization between a local directory and your workspace.
You can work offline, add screenshots to documentation, or use local development tools while keeping your files in sync with your workspace.

1. Create a new local directory.

   If you select an existing clone of your repository, Desktop will recognize it as conflicting files.

1. In the Coder Desktop app, select **File sync**.

   ![Coder Desktop File Sync screen](../../images/user-guides/desktop/coder-desktop-file-sync.png)

1. Select the **+** in the corner to select the local path, workspace, and remote path, then select **Add**:

   ![Coder Desktop File Sync add paths](../../images/user-guides/desktop/coder-desktop-file-sync-add.png)

1. File sync clones your workspace directory to your local directory, then watches for changes:

   ![Coder Desktop File Sync watching](../../images/user-guides/desktop/coder-desktop-file-sync-watching.png)

   For more information about the current status, hover your mouse over the status.

File sync excludes version control system directories like `.git/` from synchronization, so keep your Git-cloned repository wherever you run Git commands.
This means that if you use an IDE with a built-in terminal to edit files on your remote workspace, that should be the Git clone and your local directory should be for file syncs.

> [!NOTE]
> Coder Desktop uses `alpha` and `beta` to distinguish between the:
>
> - Local directory: `alpha`
> - Remote directory: `beta`

### File sync conflicts

File sync shows a `Conflicts` status when it detects conflicting files.

You can hover your mouse over the status for the list of conflicts:

![Desktop file sync conflicts mouseover](../../images/user-guides/desktop/coder-desktop-file-sync-conflicts-mouseover.png)

If you encounter a synchronization conflict, delete the conflicting file that contains changes you don't want to keep.

## Troubleshooting

<a id="accessing-web-apps-in-a-secure-browser-context"></a>

### Access web apps in a secure browser context

Some web applications require a [secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts) to function correctly.
A browser typically considers an origin secure if the connection is to `localhost`, or over `HTTPS`.

Because Coder Connect uses its own hostnames and does not provide TLS to the browser, Google Chrome and Firefox will not allow any web APIs that require a secure context.
Even though the browser displays a warning about an insecure connection without `HTTPS`, the underlying tunnel is encrypted with WireGuard in the same fashion as other Coder workspace connections (e.g. `coder port-forward`).

<details><summary>If you require secure context web APIs, identify the workspace hostnames as secure in your browser settings.</summary>

<div class="tabs">

### Chrome

1. Open Chrome and visit `chrome://flags/#unsafely-treat-insecure-origin-as-secure`.

1. Enter the full workspace hostname, including the `http` scheme and the port (e.g. `http://your-workspace.coder:8080`), into the **Insecure origins treated as secure** text field.

   If you need to enter multiple URLs, use a comma to separate them.

   ![Google Chrome insecure origin settings](../../images/user-guides/desktop/chrome-insecure-origin.png)

1. Ensure that the dropdown to the right of the text field is set to **Enabled**.

1. You will be prompted to relaunch Google Chrome at the bottom of the page. Select **Relaunch** to restart Google Chrome.

1. On relaunch and subsequent launches, Google Chrome will show a banner stating "You are using an unsupported command-line flag". This banner can be safely dismissed.

1. Web apps accessed on the configured hostnames and ports will now function correctly in a secure context.

### Firefox

1. Open Firefox and visit `about:config`.

1. Read the warning and select **Accept the Risk and Continue** to access the Firefox configuration page.

1. Enter `dom.securecontext.allowlist` into the search bar at the top.

1. Select **String** on the entry with the same name at the bottom of the list, then select the plus icon on the right.

1. In the text field, enter the full workspace hostname, without the `http` scheme and port: `your-workspace.coder`. Then select the tick icon.

   If you need to enter multiple URLs, use a comma to separate them.

   ![Firefox insecure origin settings](../../images/user-guides/desktop/firefox-insecure-origin.png)

1. Web apps accessed on the configured hostnames will now function correctly in a secure context without requiring a restart.

</div>

</details>

We are planning some changes to Coder Desktop that will make accessing secure context web apps easier in future versions.

---

# Manage workspaces

Source: https://coder.com/docs/user-guides/workspace-management

A workspace is the environment where a developer or a coding agent works.
Developers and agents in a team each work from their own workspace and can use [multiple IDEs](./workspace-access/index.md).

A developer creates a workspace from a
[shared template](../admin/templates/index.md). This lets an entire team work in
environments that are identically configured and provisioned with the same
resources.

<a id="creating-workspaces"></a>

## Create workspaces

You can create a workspace in the UI. Log in to your Coder instance, go to the
**Templates** tab, find the template you need, and select **Create Workspace**.

![Creating a workspace in the UI](../images/creating-workspace-ui.png)

When you create a workspace, you will be prompted to give it a name. You might
also be prompted to set some parameters that the template provides.

You can manage your existing templates in the **Workspaces** tab.

You can also create a workspace from the command line:

Each Coder user has their own workspaces created from
[templates](../admin/templates/index.md):

```sh
# create a workspace from the template; specify any variables
coder create --template="<templateName>" <workspaceName>

# show the resources behind the workspace and how to connect
coder show <workspace-name>
```

### Workspace name rules and restrictions

| Constraint       | Rule                                       |
|------------------|--------------------------------------------|
| Start/end with   | Must start and end with a letter or number |
| Character types  | Letters, numbers, and hyphens only         |
| Length           | 1-32 characters                            |
| Case sensitivity | Case-insensitive (lowercase recommended)   |
| Reserved names   | Cannot use `new` or `create`               |
| Uniqueness       | Must be unique within your workspaces      |

Renaming a workspace after you create it is off by default. A template admin can
allow it per template. Refer to
[Workspace renaming](../admin/templates/managing-templates/index.md#workspace-renaming).

## Workspace filtering

In the Coder UI, you can filter your workspaces using pre-defined filters or
Coder's filter query. Filters follow the pattern `[filter name]:[filter text]`
and multiple filters can be specified separated by a space i.e
`owner:me status:running`

The following filters are supported:

- `owner` - Represents the `username` of the owner. You can also use `me` as a
  convenient alias for the logged-in user, e.g., `owner:me`
- `user` - Workspaces a user owns, plus workspaces shared with them directly
  or through a group they belong to. Accepts a `username`, user ID, or `me`,
  e.g., `user:me`
- `name` - Name of the workspace.
- `template` - Name of the template.
- `status` - Indicates the status of the workspace, e.g, `status:failed` For a
  list of supported statuses, see
  [WorkspaceStatus documentation](https://pkg.go.dev/github.com/coder/coder/codersdk#WorkspaceStatus).
- `outdated` - Filters workspaces using an outdated template version, e.g,
  `outdated:true`
- `dormant` - Filters workspaces based on the dormant state, e.g `dormant:true`
- `has-agent` - Only applicable for workspaces in "start" transition. Stopped
  and deleted workspaces don't have agents. List of supported values
  `connecting|connected|timeout|disconnected`, e.g, `has-agent:connecting`
- `id` - Workspace UUID
- `healthy` - Only applicable for workspaces in "start" transition. `healthy:false` is an alias for `has-agent:timeout,disconnected`, `healthy:true` is an alias for `has-agent:connected`.
- `include_agent_metadata` - Not a filter: expands each agent in the API
  response with the named agent metadata keys, e.g,
  `include_agent_metadata:cpu_usage`. Repeat the key to request multiple
  metadata items. Keys match case-insensitively.

<a id="updating-workspaces"></a>

## Update workspaces

After updating the default version of the template that a workspace was created
from, you can update the workspace.

![Updating a workspace](../images/workspace-update.png)

If the workspace is running, Coder stops it, updates it, then starts the
workspace again.

<a id="updating-via-the-cli"></a>

### Update with the CLI

Update a workspace through the command line:

```sh
coder update <workspace-name>
```

### Automatic updates

It can be tedious to manually update a workspace everytime an update is pushed
to a template. Users can choose to opt-in to automatic updates to update to the
active template version whenever the workspace is started.

Note: If a template is updated such that new parameter inputs are required from
the user, autostart will be disabled for the workspace until the user has
manually updated the workspace.

![Automatic Updates](../images/workspace-automatic-updates.png)

## Bulk operations

Admins may apply bulk operations (update, delete, start, stop) in the
**Workspaces** tab. Select the workspaces you'd like to modify with the
checkboxes on the left, then use the top-right **Actions** dropdown to apply the
operation.

The start and stop operations can be applied even when the selected workspaces
are not all in the same state. Bulk start will only apply to selected workspaces
that are currently stopped, and bulk stop will only apply to selected workspaces
that are currently running. For update, delete, and stop, the user is prompted
for confirmation before any action is taken.

![Bulk workspace actions](../images/user-guides/workspace-bulk-actions.png)

<a id="starting-and-stopping-workspaces"></a>

## Start and stop workspaces

By default, you manually start and stop workspaces as you need. You can also
schedule a workspace to start and stop automatically.

To set a workspace's schedule, go to the workspace, then **Settings** >
**Schedule**.

![Scheduling UI](../images/schedule.png)

Coder might also stop a workspace automatically if there is a
[template update](../admin/templates/managing-templates/index.md#update-templates)
available.

Learn more about [workspace lifecycle](./workspace-lifecycle.md) and our
[scheduling features](./workspace-scheduling.md).

## Workspace resources

Workspaces in Coder are started and stopped, often based on whether there was
any activity or if there was a [template update](../admin/templates/index.md)
available.

Resources are often destroyed and re-created when a workspace is restarted,
though the exact behavior depends on the template. For more information, see
[Resource Persistence](../admin/templates/extending-templates/resource-persistence.md).

<a id="repairing-workspaces"></a>

## Repair workspaces

Use the following command to re-enter template input variables in an existing
workspace. This command is useful when a workspace fails to build because its
state is out of sync with the template.

```sh
coder update <your workspace name> --always-prompt
```

First, try re-entering parameters from a workspace. In the Coder UI, you can
filter your workspaces using pre-defined filters or employing the Coder's filter
query. Take a look at the following examples to understand how to use the
Coder's filter query:

- To find the workspaces that you own, use the filter `owner:me`.
- To find workspaces that are currently running, use the filter
  `status:running`.

![Re-entering template variables](../images/templates/template-variables.png)

You can also do this in the CLI with the following command:

```sh
coder update <your workspace name> --always-prompt
```

If that does not work, a Coder admin can manually push and pull the Terraform
state for a given workspace. This can lead to state corruption or deleted
resources if you do not know what you are doing.

```sh
coder state pull <username>/<workspace name>
# Make changes
coder state push <username>/<workspace name>
```

## Logging

Coder stores macOS and Linux logs at the following locations:

| Service           | Location                         |
|-------------------|----------------------------------|
| `startup_script`  | `/tmp/coder-startup-script.log`  |
| `shutdown_script` | `/tmp/coder-shutdown-script.log` |
| Agent             | `/tmp/coder-agent.log`           |

> [!NOTE]
> Logs are truncated once they reach 5&nbsp;MB in size.

---

# Shared workspaces

Source: https://coder.com/docs/user-guides/shared-workspaces

Multiple users can securely connect to a single Coder workspace for programming and debugging.

<!-- Insert screenshot of UI here -->

## Features

Workspace sharing is available to all Coder users by default, but platform admins with a Premium subscription can choose to disable sharing within their organizations or for their entire deployment.

Owners of a workspace can grant access to other users or groups with scoped roles.

This is helpful in a number of scenarios, including:

- Developers can do ad-hoc debugging or pair programming.
- A workspace can be owned by a group of users for QA, on-call rotations, or shared staging.
- AI workflows where an agent prepares a workspace and a developer takes over to review or finalize the work (ex. with [Coder Agents](https://coder.com/docs/ai-coder/agents).)

<a id="getting-started"></a>

## Get started

Workspaces can be shared through either the Coder CLI or UI.

Before you begin, ensure that you have a version of Coder with workspace sharing enabled and that your account has permission to share workspaces. This is true by default if you are an OSS user, but deployments with Premium licenses may be restricted by admins.

### CLI

To share a workspace:

- `coder sharing share <workspace> --user alice`
  - Shares the workspace with a single user, `alice`, with `use` permissions
- `coder sharing share <workspace> --user alice:admin,bob`
  - Shares the workspace with two users - `alice` with `admin` permissions, and `bob` with `use` permissions
- `coder sharing share <workspace> --group contractor`
  - Shares the workspace with `contractor`, which is a group of users

To remove sharing from a workspace:

- `coder sharing remove <workspace> --user alice`
  - Workspace is no longer shared with the user `alice`.
- `coder sharing remove <workspace> --group contractor`
  - Workspace is no longer shared with the group `contractor`.

> [!IMPORTANT]
> The workspace must be restarted for the user or group removal to take effect.

To show who a workspace is shared with:

- `coder sharing status <workspace>`

To list shared workspaces:

- `coder list --search shared:true`
- `coder list --search shared_with_user:me`
- `coder list --search shared_with_user:<user>`
- `coder list --search shared_with_group:<group>`

To list the workspaces you own together with the ones shared with you,
directly or through a group:

- `coder list --search user:me`

### UI

<a id="sharing-your-workspace"></a>

#### Share your workspace

1. Open a workspace that you own.

1. Locate and select the 'Share' button.

![Sharing a workspace](../images/user-guides/workspace-sharing-button-highlight.png)

1. Add the users or groups that you want to share the workspace with. For each one, select a role.

![Sharing with a user or group](../images/user-guides/workspace-sharing-roles.png)

- `use` allows for connection via SSH and apps, the ability to start and stop the workspace, view logs and stats, and update on start when required.
- `admin` allows for all of the above, as well as the ability to rename the workspace, update at any time, and invite others with the `use` role.
- Neither role allows for the user to delete the workspace.
- After removing a user/group, a workspace restart is required for the removal to take effect.

<a id="using-a-shared-workspace"></a>

#### Use a shared workspace

Once a workspace is shared, you can find the shared workspace by filtering for "Shared" in the Workspaces page.

![Sharing with a user or group](../images/user-guides/workspace-sharing-shared-view.png)

<a id="accessing-workspace-apps-in-shared-workspaces"></a>

#### Access workspace apps in shared workspaces

Sharing a workspace grants SSH and terminal access to other users. However,
workspace apps like code-server may return a **404 page** for non-owners
depending on how the app is routed.

By default, workspace apps that don't set `subdomain = true` use **path-based
routing** (e.g., `coder.example.com/@user/workspace/apps/code-server/`).
Path-based apps share the same origin as the Coder dashboard, so Coder blocks
non-owners from accessing them to prevent
[cross-site scripting risks](../tutorials/best-practices/security-best-practices.md#disable-path-based-apps).
This restriction applies even when the user has been granted access through
workspace sharing.

To allow other users to access workspace apps, configure subdomain-based access:

1. Set a
   [wildcard access URL](../admin/networking/wildcard-access-url.md)
   on your deployment
   (e.g., `CODER_WILDCARD_ACCESS_URL=*.coder.example.com`).
2. Set `subdomain = true` on the workspace app. For example, if you use the
   [code-server module](https://registry.coder.com/modules/coder/code-server):

   ```tf
   module "code-server" {
     source    = "registry.coder.com/coder/code-server/coder"
     agent_id  = coder_agent.main.id
     subdomain = true
     # ...
   }
   ```

Subdomain-based apps run in an isolated browser security context, so Coder
allows other users to access them without additional configuration.

### Policies

There are several sharing policy levels that can be selected on a per-organization basis.

- **Everyone**: anybody can share their workspace with any individual or group in the same organization.
- **Service Accounts Only**: only workspaces owned by service accounts can be shared with any individual or group in the same organization.
- **Disabled**: workspaces within the organization cannot be shared.

The **Disabled** policy applies to every workspace in the organization.
It overrides the sharing permission of any role held by a member of that organization, including Organization Admin.

The **Disabled** policy can also be applied to the entire deployment by [setting the `CODER_DISABLE_WORKSPACE_SHARING` environment variable, or by using the corresponding command argument or config value](https://coder.com/docs/reference/cli/server#--disable-workspace-sharing).

---

# Manage workspace schedules

Source: https://coder.com/docs/user-guides/workspace-scheduling

Scheduling helps minimize cloud costs without sacrificing the availability of
your workspaces.

You can configure each workspace to automatically start in the morning, and
automatically stop once you log off. Coder also features an inactivity timeout,
configured by your template admin, which will stop a workspace when a user's
absence is detected.

To learn more workspace states and schedule, read the
[workspace lifecycle](../user-guides/workspace-lifecycle.md) documentation.

## Where to find the schedule settings

Select any workspace the **Workspaces** tab of the dashboard, then go to
**Workspace settings** in the top right.

![Workspace settings location](../images/user-guides/workspace-settings-location.png)

Then open the **Schedule** tab to see your workspace scheduling options.

![Workspace schedule settings](../images/user-guides/schedule-settings-workspace.png)

## Autostart

Autostart must be enabled in the template settings by your administrator.

Use autostart to start a workspace at a specified time and which days of the
week. Also, you can choose your preferred timezone. Admins may restrict which
days of the week your workspace is allowed to autostart.

![Autostart UI](../images/workspaces/autostart.png)

## Autostop

Use autostop to stop a workspace after a number of hours.
Autostop won't stop a workspace if you're still using it.
It will wait for the user to become inactive before checking connections again (1&nbsp;hour by default).
Template admins can modify this duration with the **activity bump** template setting.

> [!NOTE]
> Autostop must be enabled on the template prior to workspace creation, it is not applied to existing running workspaces.

![Autostop UI](../images/workspaces/autostop.png)

## Activity detection

Workspaces automatically shut down after a period of inactivity. The **activity bump**
duration can be configured at the template level and is visible in the autostop description
for your workspace.

### What counts as workspace activity?

A workspace is considered "active" when Coder detects one or more active sessions with your workspace. Coder specifically tracks these session types:

- **VSCode sessions**: Using code-server or VS Code with a remote extension
- **JetBrains IDE sessions**: Using JetBrains Gateway or remote IDE plugins
- **Terminal sessions**: Using the web terminal (including reconnecting to the web terminal)
- **SSH sessions**: Connecting via `coder ssh` or SSH config integration
- **AI agent task status**: When a coding agent reports "working" status, the
  workspace deadline is extended

Activity is only detected when there is at least one active session. An open session will keep your workspace marked as active and prevent automatic shutdown.

The following actions do **not** count as workspace activity:

- Viewing workspace details in the dashboard
- Viewing or editing workspace settings
- Viewing build logs or audit logs
- Accessing ports through direct URLs without an active session
- Background agent statistics reporting (note: AI agent _task status_
  reporting is different and does count as activity, see above)

To avoid unexpected cloud costs, close your connections, this includes IDE windows, SSH sessions, and others, when you finish using your workspace.

## Autostop requirement

> [!NOTE]
> Autostop requirement is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Licensed template admins may enforce a required stop for workspaces to apply
updates or undergo maintenance. These stops ignore any active connections or
inactivity bumps. Rather than being specified with a CRON, admins set a
frequency for updates, either in **days** or **weeks**. Workspaces will apply
the template autostop requirement on the given day **in the user's timezone**
and specified quiet hours (see below).

Admins: See the template schedule settings for more information on configuring
Autostop Requirement.

### User quiet hours

> [!NOTE]
> User quiet hours are a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

User quiet hours can be configured in the user's schedule settings page.
Workspaces on templates with an autostop requirement will only be forcibly
stopped due to the policy at the **start** of the user's quiet hours.

![User schedule settings](../images/admin/templates/schedule/user-quiet-hours.png)

## Scheduling configuration examples

The combination of autostart, autostop, and the activity bump create a
powerful system for scheduling your workspace. However, synchronizing all of
them simultaneously can be somewhat challenging, here are a few example
configurations to better understand how they interact.

> [!NOTE]
> The activity bump must be configured by your template admin.

<a id="working-hours"></a>

### Work schedule

The intended configuration for autostop is to combine it with autostart, and set
a "working schedule" for your workspace. It's pretty intuitive:

If I want to use my workspace from 9 to 5 on weekdays, I would set my autostart to 9:00 AM every day with an autostop of 9&nbsp;hours.
My workspace will always be available during these hours, regardless of how long I spend away from my laptop.
If I end up working overtime and log off at 6:00 PM, the activity bump will kick in, postponing the shutdown until 7:00 PM.

<a id="basing-solely-on-activity-detection"></a>

#### Rely solely on activity detection

If you'd like to ignore the TTL from autostop and have your workspace solely
function on activity detection, you can set your autostop equal to activity
bump duration.

Let's say that both are set to 5&nbsp;hours.
When either your workspace autostarts or you sign in, you will have confidence that the only condition for shutdown is 5&nbsp;hours of inactivity.

## Dormancy

> [!NOTE]
> Dormancy is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Dormancy automatically deletes workspaces that remain unused for long
durations. Template admins configure a dormancy threshold that determines how long
a workspace can be inactive before it is marked as `dormant`. A separate setting
determines how long workspaces will remain in the dormant state before automatic deletion.

Licensed admins may also configure failure cleanup, which will automatically
delete workspaces that remain in a `failed` state for too long.

---

# Workspace lifecycle

Source: https://coder.com/docs/user-guides/workspace-lifecycle

Workspaces are flexible, reproducible, and isolated units of compute. Workspaces
are created via Terraform, managed through the Coder control plane, accessed
through the Coder agent, then stopped and deleted again by Terraform.

This page covers how workspaces move through this lifecycle. To learn about
automating workspace schedules for cost control, read the
[workspace scheduling docs](./workspace-scheduling.md).

## Workspace ephemerality

Workspaces are composed of resources which may be _ephemeral_ or _persistent_.
Persistent resources stay provisioned when the workspace is stopped, where as
ephemeral resources are destroyed and recreated on restart. All resources are
destroyed when a workspace is deleted.

Template administrators can learn more about resource configuration in the
[extending templates docs](../admin/templates/extending-templates/resource-persistence.md).

## Workspace States

Generally, there are 3 states that a workspace may fall into:

- Running: Started and ready for connections
- Stopped: Ephemeral resources destroyed, persistent resources idle
- Deleted: All resources destroyed, workspace records removed from database

If some error occurs during the above, a workspace may fall into one of the
following broken states:

- Failed: Failure during provisioning, no resource consumption
- Unhealthy: Resources have been provisioned, but the agent can't facilitate
  connections

## Workspace creation

Workspaces are created from [templates](../admin/templates/index.md) via the
CLI, API, or dashboard.

By default, there is no limit on the number of workspaces a user may create,
regardless of the template's resource demands. Enterprise administrators may
limit the number of workspaces per template, group, and organization using
[quotas](../admin/users/quotas.md) to prevent over provisioning and control
costs.

When a user creates a workspace, they're sending a build request to the control
plane. Coder takes this and uses [Terraform](https://www.terraform.io/) to
provision a workspace defined by your [template](../admin/templates/index.md).
Generally, templates define the resources and environment of a workspace.

The resources that run the agent are described as _computational resources_,
while those that don't are called _peripheral resources_. A workspace must
contain some computational resource to run the Coder agent process.

The provisioned workspace's computational resources start the agent process,
which opens connections to your workspace via SSH, the terminal, and IDES such
as [JetBrains](./workspace-access/jetbrains/index.md) or
[VSCode](./workspace-access/vscode.md).

Once started, the Coder agent is responsible for running your workspace startup
scripts. These may configure tools, service connections, or personalization with
[dotfiles](./workspace-dotfiles.md). For complex initialization with multiple
dependent scripts, see
[Workspace Startup Coordination](../admin/templates/startup-coordination/index.md).

Once these steps have completed, your workspace will now be in the `Running`
state. You can access it via any of the [supported methods](./index.md), stop it
when you're away, or delete it once it's no longer in use.

<a id="stopping-workspaces"></a>

## Stop workspaces

Workspaces may be stopped manually by users and admins in the dashboard, CLI, or
API. Workspaces may be automatically stopped due to template updates or
inactivity by [scheduling configuration](./workspace-scheduling.md).

Once stopped, a workspace may resume running by starting it manually, or via
user connection if automatic start is enabled.

<a id="deleting-workspaces"></a>

## Delete workspaces

Similarly to stopping, workspaces may be deleted manually or automatically by
Coder through workspace dormancy.

A delete workspace build runs `terraform destroy`, destroying both persistent
and ephemeral resources. This action can not be reverted.

When enabled on enterprise deployments, workspaces will become dormant after a
specified duration of inactivity. Then, if left dormant, the workspaces will be
queued for deletion. Learn about configuring workspace dormancy in the template
scheduling docs.

### Orphan resources

Typically, when a workspace is deleted, all of the workspace's resources are
deleted along with it. Rarely, one may wish to delete a workspace without
deleting its resources, e.g. a workspace in a broken state. Users with the
Template Admin role have the option to do so both in the UI, and also in the CLI
by running the delete command with the `--orphan` flag. This option should be
considered cautiously as orphaning may lead to unaccounted cloud resources.

## Broken workspace states

During a workspace start or stop build, one of two errors may lead to a broken
state. If the call to `terraform apply` fails to correctly provision resources,
a workspace build has **failed**. If the computational resources fail to connect
the agent, a workspace becomes **unhealthy**.

A failed workspace is most often caused by misalignment from the definition in
your template's Terraform file and the target resources on your infrastructure.
Unhealthy workspaces are usually caused by a misconfiguration in the agent or
workspace startup scripts.

## Workspace build times

After a successful build, you can see a timing breakdown of the workspace
startup process from the dashboard (starting in v2.17). We capture and display
both time taken to provision the workspace's compute and agent startup steps.
These include any
[`coder_script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/script)s
such as [dotfiles](./workspace-dotfiles.md) or
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
startups.

![Workspace build timings UI](../images/admin/templates/troubleshooting/workspace-build-timings-ui.png)

### Next steps

- [Connecting to your workspace](./index.md)
- [Creating templates](../admin/templates/index.md)
- [Workspace scheduling](./workspace-scheduling.md)

---

# Dev Containers

Source: https://coder.com/docs/user-guides/devcontainers

[Dev containers](https://containers.dev/) define your development environment
as code using a `devcontainer.json` file. Coder's Dev Containers integration
uses the [`@devcontainers/cli`](https://github.com/devcontainers/cli) and
[Docker](https://www.docker.com) to seamlessly build and run these containers,
with management in your dashboard.

This guide covers the Dev Containers integration. For workspaces without Docker,
administrators can configure
[Envbuilder](../../admin/integrations/devcontainers/envbuilder/index.md) instead,
which builds the workspace image itself from your dev container configuration.

![Two dev containers running as sub-agents in a Coder workspace](../../images/user-guides/devcontainers/devcontainer-running.png)_Dev containers appear as sub-agents with their own apps, SSH access, and port forwarding_

## Prerequisites

- Coder version 2.24.0 or later
- Docker available inside your workspace
- The `@devcontainers/cli` installed in your workspace

Dev Containers integration is enabled by default. Your workspace needs Docker
(via Docker-in-Docker or a mounted socket) and the devcontainers CLI. Most
templates with Dev Containers support include both. See
[Configure a template for dev containers](../../admin/integrations/devcontainers/integration.md)
for setup details.

## Features

- Automatic dev container detection from repositories
- Seamless container startup during workspace initialization
- Change detection with outdated status indicator
- On-demand container rebuild via dashboard button
- Template-defined apps, scripts, and environment variables via Terraform (see [limitations](../../admin/integrations/devcontainers/integration.md#interaction-with-devcontainerjson-customizations))
- Integrated IDE experience with VS Code
- Direct SSH access to containers
- Automatic port detection

<a id="getting-started"></a>

## Get started

### Add a devcontainer.json

Add a `devcontainer.json` file to your repository. This file defines your
development environment. You can place it in:

- `.devcontainer/devcontainer.json` (recommended)
- `.devcontainer.json` (root of repository)
- `.devcontainer/<folder>/devcontainer.json` (for multiple configurations)

The third option allows monorepos to define multiple dev container
configurations in separate sub-folders. See the
[Dev Container specification](https://containers.dev/implementors/spec/#devcontainerjson)
for details.

Here's a minimal example:

```json
{
  "name": "My Dev Container",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu"
}
```

For more configuration options, see the
[Dev Container specification](https://containers.dev/).

### Start your dev container

Coder automatically discovers dev container configurations in your repositories
and displays them in your workspace dashboard. From there, you can start a dev
container with a single click.

![Discovered dev containers with Start buttons](../../images/user-guides/devcontainers/devcontainer-discovery.png)_Coder detects dev container configurations and displays them with a Start button_

If your template administrator has configured automatic startup (via the
`coder_devcontainer` Terraform resource or autostart settings), your dev
container will build and start automatically when the workspace starts.

### Connect to your dev container

Once running, your dev container appears as a sub-agent in your workspace
dashboard. You can connect via:

- **Web terminal** in the Coder dashboard
- **SSH** using `coder ssh <workspace>.<agent>`
- **VS Code** using the "Open in VS Code Desktop" button

See [Working with dev containers](./working-with-dev-containers.md) for detailed
connection instructions.

## How it works

The Dev Containers integration uses the `devcontainer` command from
[`@devcontainers/cli`](https://github.com/devcontainers/cli) to manage
containers within your Coder workspace.

When a workspace with Dev Containers integration starts:

1. If the template defines `coder_app`, `coder_script`, or `coder_env` resources
   attached to the dev container, a sub-agent is pre-created with these resources.
1. The workspace initializes the Docker environment.
1. The integration detects repositories with dev container configurations.
1. Detected dev containers appear in the Coder dashboard.
1. If auto-start is configured (via `coder_devcontainer` or autostart settings),
   the integration builds and starts the dev container automatically.
1. Coder creates a sub-agent (or updates the pre-created one) for the running
   container, enabling direct access.

Without auto-start, users can manually start discovered dev containers from the
dashboard.

### Agent naming

Each dev container gets its own agent name, derived from the workspace folder
path. For example, a dev container with workspace folder `/home/coder/my-app`
will have an agent named `my-app`.

Agent names are sanitized to contain only lowercase alphanumeric characters and
hyphens. You can also set a
[custom agent name](./customizing-dev-containers.md#custom-agent-name)
in your `devcontainer.json`.

## Limitations

- **Linux only**: Dev Containers are currently not supported in Windows or
  macOS workspaces
- Changes to `devcontainer.json` require manual rebuild using the dashboard
  button
- The `forwardPorts` property in `devcontainer.json` with `host:port` syntax
  (e.g., `"db:5432"`) for Docker Compose sidecar containers is not yet
  supported. For single-container dev containers, use `coder port-forward` to
  access ports directly on the sub-agent.
- Some advanced dev container features may have limited support

## Next steps

- [Working with dev containers](./working-with-dev-containers.md) — SSH, IDE
  integration, and port forwarding
- [Customizing dev containers](./customizing-dev-containers.md) — Custom agent
  names, apps, and display options
- [Troubleshooting dev containers](./troubleshooting-dev-containers.md) —
  Diagnose common issues
- [Dev Container specification](https://containers.dev/) — Advanced
  configuration options
- [Dev Container features](https://containers.dev/features) — Enhance your
  environment with pre-built tools

---

# Work with Dev Containers

Source: https://coder.com/docs/user-guides/devcontainers/working-with-dev-containers

The dev container integration appears in your Coder dashboard, providing a
visual representation of the running environment:

![Two dev containers running as sub-agents in a Coder workspace](../../images/user-guides/devcontainers/devcontainer-running.png)_Dev containers appear as sub-agents with their own apps, SSH access, and port forwarding_

## SSH access

Each dev container has its own agent name, derived from the workspace folder
(e.g., `/home/coder/my-project` becomes `my-project`). You can find agent names
in your workspace dashboard, or see
[Agent naming](./index.md#agent-naming) for details on how names are generated.

<a id="using-the-coder-cli"></a>

### Use the Coder CLI

The simplest way to SSH into a dev container is using `coder ssh` with the
workspace and agent name:

```console
coder ssh <workspace>.<agent>
```

For example, to connect to a dev container with agent name `my-project` in
workspace `my-workspace`:

```console
coder ssh my-workspace.my-project
```

To SSH into the main workspace agent instead of the dev container:

```console
coder ssh my-workspace
```

<a id="using-openssh-config-ssh"></a>

### Use OpenSSH (config-ssh)

You can also use standard OpenSSH tools after generating SSH config entries with
`coder config-ssh`:

```console
coder config-ssh
```

This creates a wildcard SSH host entry that matches all your workspaces and
their agents, including dev container sub-agents. You can then connect using:

```console
ssh my-project.my-workspace.me.coder
```

The default hostname suffix is `.coder`. If your organization uses a different
suffix, adjust the hostname accordingly. The suffix can be configured via
[`coder config-ssh --hostname-suffix`](../../reference/cli/config-ssh.md) or
by your deployment administrator.

This method works with any SSH client, IDE remote extensions, `rsync`, `scp`,
and other tools that use SSH.

## Web terminal access

Once your workspace and dev container are running, you can use the web terminal
in the Coder interface to execute commands directly inside the dev container.

![Coder web terminal with dev container](../../images/user-guides/devcontainers/devcontainer-web-terminal.png)

## IDE integration (VS Code)

You can open your dev container directly in VS Code by:

1. Selecting **Open in VS Code Desktop** from the dev container agent in the
   Coder web interface.
1. Using the Coder CLI:

   ```console
   coder open vscode <workspace>.<agent>
   ```

   For example:

   ```console
   coder open vscode my-workspace.my-project
   ```

VS Code will automatically detect the dev container environment and connect
appropriately.

While optimized for VS Code, other IDEs with dev container support may also
work.

## Port forwarding

Since dev containers run as sub-agents, you can forward ports directly to them
using standard Coder port forwarding:

```console
coder port-forward <workspace>.<agent> --tcp 8080
```

For example, to forward port 8080 from a dev container with agent name
`my-project`:

```console
coder port-forward my-workspace.my-project --tcp 8080
```

This forwards port 8080 on your local machine directly to port 8080 in the dev
container. Coder also automatically detects ports opened inside the container.

<a id="exposing-ports-on-the-parent-workspace"></a>

### Expose ports on the parent workspace

If you need to expose dev container ports through the parent workspace agent
(rather than the sub-agent), you can use the
[`appPort`](https://containers.dev/implementors/json_reference/#image-specific)
property in your `devcontainer.json`:

```json
{
  "appPort": ["8080:8080", "4000:3000"]
}
```

This maps container ports to the parent workspace, which can then be forwarded
using the main workspace agent.

## Dev container features

You can use standard [dev container features](https://containers.dev/features)
in your `devcontainer.json` file. Coder also maintains a
[repository of features](https://github.com/coder/devcontainer-features) to
enhance your development experience.

For example, the
[code-server](https://github.com/coder/devcontainer-features/blob/main/src/code-server)
feature from the [Coder features repository](https://github.com/coder/devcontainer-features):

```json
{
  "features": {
    "ghcr.io/coder/devcontainer-features/code-server:1": {
      "port": 13337,
      "host": "0.0.0.0"
    }
  }
}
```

<a id="rebuilding-dev-containers"></a>

## Rebuild dev containers

When you modify your `devcontainer.json`, you need to rebuild the container for
changes to take effect. Coder detects changes and shows an **Outdated** status
next to the dev container.

![Dev container showing Outdated status with rebuild option](../../images/user-guides/devcontainers/devcontainer-outdated.png)_The Outdated indicator appears when changes to devcontainer.json are detected_

Select **Rebuild** to recreate your dev container with the updated configuration.

---

# Customizing dev containers

Source: https://coder.com/docs/user-guides/devcontainers/customizing-dev-containers

Coder supports custom configuration in your `devcontainer.json` file through the
`customizations.coder` block. These options let you control how Coder interacts
with your dev container without requiring template changes.

> [!TIP]
>
> Alternatively, template administrators can also define apps, scripts, and
> environment variables for dev containers directly in Terraform. See
> [Attach resources to dev containers](../../admin/integrations/devcontainers/integration.md#attach-resources-to-dev-containers)
> for details.

## Ignore a dev container

Use the `ignore` option to hide a dev container from Coder completely:

```json
{
  "name": "My Dev Container",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "customizations": {
    "coder": {
      "ignore": true
    }
  }
}
```

When `ignore` is set to `true`:

- The dev container won't appear in the Coder UI
- Coder won't manage or monitor the container

This is useful for dev containers in your repository that you don't want Coder
to manage.

## Auto-start

Control whether your dev container should auto-start using the `autoStart`
option:

```json
{
  "name": "My Dev Container",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "customizations": {
    "coder": {
      "autoStart": true
    }
  }
}
```

When `autoStart` is set to `true`, the dev container automatically builds and
starts during workspace initialization.

When `autoStart` is set to `false` or omitted, the dev container is discovered
and shown in the UI, but users must manually start it.

> [!NOTE]
>
> The `autoStart` option only takes effect when your template administrator has
> enabled [`CODER_AGENT_DEVCONTAINERS_DISCOVERY_AUTOSTART_ENABLE`](../../admin/integrations/devcontainers/integration.md#coder_agent_devcontainers_discovery_autostart_enable).
> If this setting is disabled at the template level, containers won't auto-start
> regardless of this option.

## Custom agent name

Each dev container gets an agent name derived from the workspace folder path by
default. You can set a custom name using the `name` option:

```json
{
  "name": "My Dev Container",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "customizations": {
    "coder": {
      "name": "my-custom-agent"
    }
  }
}
```

The name must contain only lowercase letters, numbers, and hyphens. This name
appears in `coder ssh` commands and the dashboard (e.g.,
`coder ssh my-workspace.my-custom-agent`).

## Display apps

Control which built-in Coder apps appear for your dev container using
`displayApps`:

![Dev container with all display apps disabled](../../images/user-guides/devcontainers/devcontainer-apps-bar.png)_Disable built-in apps to reduce clutter or guide developers toward preferred tools_

```json
{
  "name": "My Dev Container",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "customizations": {
    "coder": {
      "displayApps": {
        "web_terminal": true,
        "ssh_helper": true,
        "port_forwarding_helper": true,
        "vscode": true,
        "vscode_insiders": false
      }
    }
  }
}
```

Available display apps:

| App                      | Description                  | Default |
|--------------------------|------------------------------|---------|
| `web_terminal`           | Web-based terminal access    | `true`  |
| `ssh_helper`             | SSH connection helper        | `true`  |
| `port_forwarding_helper` | Port forwarding interface    | `true`  |
| `vscode`                 | VS Code Desktop integration  | `true`  |
| `vscode_insiders`        | VS Code Insiders integration | `false` |

## Custom apps

Define custom applications for your dev container using the `apps` array:

```json
{
  "name": "My Dev Container",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "customizations": {
    "coder": {
      "apps": [
        {
          "slug": "zed",
          "displayName": "Zed Editor",
          "url": "zed://ssh/${localEnv:CODER_WORKSPACE_AGENT_NAME}.${localEnv:CODER_WORKSPACE_NAME}.${localEnv:CODER_WORKSPACE_OWNER_NAME}.coder${containerWorkspaceFolder}",
          "external": true,
          "icon": "/icon/zed.svg",
          "order": 1
        }
      ]
    }
  }
}
```

This example adds a Zed Editor button that opens the dev container directly in
the Zed desktop app via its SSH remote feature.

Each app supports the following properties:

| Property      | Type    | Description                                                   |
|---------------|---------|---------------------------------------------------------------|
| `slug`        | string  | Unique identifier for the app (required)                      |
| `displayName` | string  | Human-readable name shown in the UI                           |
| `url`         | string  | URL to open (supports variable interpolation)                 |
| `command`     | string  | Command to run instead of opening a URL                       |
| `icon`        | string  | Path to an icon (e.g., `/icon/code.svg`)                      |
| `openIn`      | string  | `"tab"` or `"slim-window"` (default: `"slim-window"`)         |
| `share`       | string  | `"owner"`, `"authenticated"`, `"organization"`, or `"public"` |
| `external`    | boolean | Open as external URL (e.g., for desktop apps)                 |
| `group`       | string  | Group name for organizing apps in the UI                      |
| `order`       | number  | Sort order for display                                        |
| `hidden`      | boolean | Hide the app from the UI                                      |
| `subdomain`   | boolean | Use subdomain-based access                                    |
| `healthCheck` | object  | Health check configuration (see below)                        |

### Health checks

Configure health checks to monitor app availability:

```json
{
  "customizations": {
    "coder": {
      "apps": [
        {
          "slug": "web-server",
          "displayName": "Web Server",
          "url": "http://localhost:8080",
          "healthCheck": {
            "url": "http://localhost:8080/healthz",
            "interval": 5,
            "threshold": 2
          }
        }
      ]
    }
  }
}
```

Health check properties:

| Property    | Type   | Description                                     |
|-------------|--------|-------------------------------------------------|
| `url`       | string | URL to check for health status                  |
| `interval`  | number | Seconds between health checks                   |
| `threshold` | number | Number of failures before marking app unhealthy |

## Variable interpolation

App URLs and other string values support variable interpolation for dynamic
configuration.

### Environment variables

Use `${localEnv:VAR_NAME}` to reference environment variables, with optional
default values:

```json
{
  "customizations": {
    "coder": {
      "apps": [
        {
          "slug": "my-app",
          "url": "http://${localEnv:HOST:127.0.0.1}:${localEnv:PORT:8080}"
        }
      ]
    }
  }
}
```

### Coder-provided variables

Coder provides these environment variables automatically:

| Variable                            | Description                        |
|-------------------------------------|------------------------------------|
| `CODER_WORKSPACE_NAME`              | Name of the workspace              |
| `CODER_WORKSPACE_OWNER_NAME`        | Username of the workspace owner    |
| `CODER_WORKSPACE_AGENT_NAME`        | Name of the dev container agent    |
| `CODER_WORKSPACE_PARENT_AGENT_NAME` | Name of the parent workspace agent |
| `CODER_URL`                         | URL of the Coder deployment        |
| `CONTAINER_ID`                      | Docker container ID                |

### Dev container variables

Standard dev container variables are also available:

| Variable                      | Description                                |
|-------------------------------|--------------------------------------------|
| `${containerWorkspaceFolder}` | Workspace folder path inside the container |
| `${localWorkspaceFolder}`     | Workspace folder path on the host          |

## Feature options as environment variables

When your dev container uses features, Coder exposes feature options as
environment variables. The format is `FEATURE_<FEATURE_NAME>_OPTION_<OPTION_NAME>`.

For example, with this feature configuration:

```json
{
  "features": {
    "ghcr.io/coder/devcontainer-features/code-server:1": {
      "port": 9090
    }
  }
}
```

Coder creates `FEATURE_CODE_SERVER_OPTION_PORT=9090`, which you can reference in
your apps:

```json
{
  "features": {
    "ghcr.io/coder/devcontainer-features/code-server:1": {
      "port": 9090
    }
  },
  "customizations": {
    "coder": {
      "apps": [
        {
          "slug": "code-server",
          "displayName": "Code Server",
          "url": "http://localhost:${localEnv:FEATURE_CODE_SERVER_OPTION_PORT:8080}",
          "icon": "/icon/code.svg"
        }
      ]
    }
  }
}
```

## Next steps

- [Working with dev containers](./working-with-dev-containers.md) — SSH, IDE
  integration, and port forwarding
- [Troubleshooting dev containers](./troubleshooting-dev-containers.md) —
  Diagnose common issues

---

# Troubleshooting dev containers

Source: https://coder.com/docs/user-guides/devcontainers/troubleshooting-dev-containers

## Dev container not starting

If your dev container fails to start:

1. Check the agent logs for error messages:

   - `/tmp/coder-agent.log`
   - `/tmp/coder-startup-script.log`
   - `/tmp/coder-script-[script_id].log`

1. Verify Docker is available in your workspace (see below).
1. Ensure the `devcontainer.json` file is valid JSON.
1. Check that the repository has been cloned correctly.
1. Verify the resource limits in your workspace are sufficient.

## Docker not available

Dev containers require Docker, either via a running daemon (Docker-in-Docker) or
a mounted socket from the host. Your template determines which approach is used.

**If using Docker-in-Docker**, check that the daemon is running:

```console
sudo service docker status
sudo service docker start  # if not running
```

**If using a mounted socket**, verify the socket exists and is accessible:

```console
ls -la /var/run/docker.sock
docker ps  # test access
```

If you get permission errors, your user may need to be in the `docker` group.

<a id="finding-your-dev-container-agent"></a>

## Find your dev container agent

Use `coder show` to list all agents in your workspace, including dev container
sub-agents:

```console
coder show <workspace>
```

The agent name is derived from the workspace folder path. For details on how
names are generated, see [Agent naming](./index.md#agent-naming).

## SSH connection issues

If `coder ssh <workspace>.<agent>` fails:

1. Verify the agent name using `coder show <workspace>`.
1. Check that the dev container is running:

   ```console
   docker ps
   ```

1. Check the workspace agent logs for container-related errors:

   ```console
   grep -i container /tmp/coder-agent.log
   ```

## VS Code connection issues

VS Code connects to dev containers through the Coder extension. The extension
uses the sub-agent information to route connections through the parent workspace
agent to the dev container. If VS Code fails to connect:

1. Ensure you have the latest Coder VS Code extension.
1. Verify the dev container is running in the Coder dashboard.
1. Check the parent workspace agent is healthy.
1. Try restarting the dev container from the dashboard.

## Dev container features not working

If features from your `devcontainer.json` aren't being applied:

1. Rebuild the container to ensure features are installed fresh.
1. Check the container build output for feature installation errors.
1. Verify the feature reference format is correct:

   ```json
   {
     "features": {
       "ghcr.io/devcontainers/features/node:1": {}
     }
   }
   ```

## Slow container startup

If your dev container takes a long time to start:

1. **Use a pre-built image** instead of building from a Dockerfile. This avoids
   the image build step, though features and lifecycle scripts still run.
1. **Minimize features**. Each feature executes as a separate Docker layer
   during the image build, which is typically the slowest part. Changing
   `devcontainer.json` invalidates the layer cache, causing features to
   reinstall on rebuild.
1. **Check lifecycle scripts**. Commands in `postStartCommand` run on every
   container start. Commands in `postCreateCommand` run once per build, so
   they execute again after each rebuild.

<a id="getting-more-help"></a>

## Get more help

If you continue to experience issues:

1. Collect logs from `/tmp/coder-agent.log` (both workspace and container).
1. Note the exact error messages.
1. Check [Coder GitHub issues](https://github.com/coder/coder/issues) for
   similar problems.
1. Contact your Coder administrator for template-specific issues.

---

# Dotfiles

Source: https://coder.com/docs/user-guides/workspace-dotfiles

<!-- markdown-link-check-disable -->

Coder offers the `coder dotfiles <repo>` command which simplifies workspace
personalization. Our behavior is consistent with Codespaces, so
[their documentation](https://docs.github.com/en/codespaces/customizing-your-codespace/personalizing-codespaces-for-your-account#dotfiles)
explains how it loads your repo.

<!-- markdown-link-check-enable -->

You can read more on dotfiles best practices [here](https://dotfiles.github.io).

## From templates

Templates can prompt users for their dotfiles repo URL, which will personalize
your workspace automatically.

![Dotfiles in workspace creation](../images/user-guides/dotfiles-module.png)

> [!NOTE]
> Template admins: this can be enabled quite easily with a our
> [dotfiles module](https://registry.coder.com/modules/dotfiles) using just a
> few lines in the template.

## Personalize script

Templates may be configured to support executing a `~/personalize` script on
startup which users can populate with commands to customize their workspaces.

You can even fill `personalize` with `coder dotfiles <repo>`, but those looking
for a simpler approach can inline commands like so:

```sh
#!/bin/bash
sudo apt update
# Install some of my favorite tools every time my workspace boots
sudo apt install -y neovim fish cargo
```

> [!NOTE]
> Template admins: refer to
> [this module](https://registry.coder.com/modules/personalize) to enable the
> `~/personalize` script on templates.

## Setup script support

User can setup their dotfiles by creating one of the following script files in
their dotfiles repo:

- `install.sh`
- `install`
- `bootstrap.sh`
- `bootstrap`
- `script/bootstrap`
- `setup.sh`
- `setup`
- `script/setup`

If any of the above files are found (in the specified order), Coder will try to
execute the first match. After the first match is found, other files will be
ignored.

The setup script must be executable, otherwise the dotfiles setup will fail. If
you encounter this issue, you can fix it by making the script executable using
the following commands:

```sh
cd <path_to_dotfiles_repo>
chmod +x <script_name>
git commit -m "Make <script_name> executable" <script_name>
git push
```

---

# User secrets

Source: https://coder.com/docs/user-guides/user-secrets

User secrets let you store secret values in Coder and make them available in
every workspace you own.

## How user secrets work

Each user secret has:

- A name, used to manage the secret with the CLI or REST API.
- A value, which contains the sensitive content.
- An optional description.
- An optional environment variable target, file target, or both.
- An enabled flag that controls whether Coder injects the secret into your
  workspaces.

An enabled secret must have at least one of an environment variable target or a
file target. To keep a secret stored without injecting it, disable it
(`enabled = false`) instead of clearing both targets. A create or update that
would leave an enabled secret with no target is rejected with a 400 and
directs you to disable the secret instead.

Disabled secrets stay visible and editable in the CLI, REST API, and dashboard,
but are not injected into workspaces. Secrets that predate the enabled flag and
had no target were migrated to disabled, so they show as disabled and need a
target before you can enable them.

User secrets apply to all workspaces that you own.

Secret values are omitted from CLI output and REST API responses after you
create or update them.

> [!WARNING]
> Anyone with shell or file access to a workspace can read secrets injected into
> that workspace. Do not share a workspace that has injected secrets with users
> who should not access those values.

### Storage and encryption

Coder stores user secret values in the database. When
[database encryption](../admin/security/database-encryption.md) is enabled,
Coder encrypts secret values at rest. Otherwise, values are stored in plaintext
in the database.

## How your secrets reach a workspace

Coder applies your secrets when your workspace starts. The same applies any
time the workspace agent reconnects to Coder, for example after the workspace
or the agent restarts. To pick up a change to a secret while a workspace is
running, restart the workspace.

Disabling a secret (`coder secret disable`) stops it from being injected from
the next workspace start onward. Running sessions keep values that were already
injected until the agent manifest is refetched, which happens on workspace
restart. Disabling does not remove a file that was already written; the same
"Coder never deletes secret files" rule below applies.

Coder controls where a secret is delivered, not whether it is still valid.
Changing or deleting a secret in Coder does not revoke a credential that a workspace has already received.
If a credential is exposed, rotate or revoke it in the system that issued it.

### Environment variable secrets

Coder injects environment variable secrets into every new shell, terminal,
app, SSH session, and startup script that you start in your workspace.
Existing shells and processes keep the environment they were given when they
started.

| If you...                                   | ...then in your workspace                                                                                                                                                                               |
|---------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Create or update an env secret              | The change applies after the next workspace start. Until then, your running workspace continues to use the secrets it had when it last started.                                                         |
| Rename the env var (`--env NEW_NAME`)       | After the next workspace start, new shells get `NEW_NAME` and the old name is no longer set.                                                                                                            |
| Clear the env target (`--env ""`)           | Only succeeds if the secret keeps its file target or is disabled in the same request; otherwise the request is rejected with a 400. After the next workspace start, the variable is no longer injected. |
| Disable the secret (`coder secret disable`) | After the next workspace start, the variable is no longer injected. Running sessions keep the value until the agent manifest is refetched (workspace restart).                                          |
| Delete the secret                           | After the next workspace start, the variable is no longer injected.                                                                                                                                     |

To pick up a change in a long-running shell or app started after a restart,
restart that shell or app.

### File secrets

Coder writes file secrets to your workspace filesystem when the workspace
starts, before any startup scripts run. New parent directories are created as
needed. If the file already exists, Coder overwrites the contents and leaves
the existing permissions alone.

| If you...                                   | ...then in your workspace                                                                                                                                                                             |
|---------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Create or update a file secret              | The file is written or overwritten at the next workspace start.                                                                                                                                       |
| Change the file path (`--file NEW_PATH`)    | At the next workspace start, a file is written at `NEW_PATH`. **The file at the previous path stays on disk with its old value.**                                                                     |
| Clear the file target (`--file ""`)         | Only succeeds if the secret keeps its env target or is disabled in the same request; otherwise the request is rejected with a 400. **The previously-written file stays on disk with its last value.** |
| Disable the secret (`coder secret disable`) | The file is no longer written at the next workspace start. **The previously-written file stays on disk with its last value.**                                                                         |
| Delete the secret                           | **The previously-written file stays on disk with its last value.**                                                                                                                                    |

> [!IMPORTANT]
> Coder never deletes secret files it has written for you. If you remove a
> secret, change its file path, or clear the file target, the previous file
> stays in your workspace until you delete it. To remove a stale file, open
> a terminal in your workspace and run `rm <path>`. Rebuilding the workspace
> may clear stale files when your template recreates the filesystem.

Coder rejects a second secret that uses a file path you already use. Two
different paths can still resolve to the same absolute path (for example
`~/config` and `/home/coder/config`). Coder accepts both, but only one of them
ends up on disk; the workspace agent logs a warning to help spot this. Use
distinct paths to avoid the collision.

## Limits

User secrets are subject to the following limits. Coder enforces these when you
create or update a secret and rejects the request with an explanatory 400 when
you exceed one. Delete or shrink an existing secret to make room.

| Cap                                      | Value        |
|------------------------------------------|--------------|
| Total secrets per user                   | 50           |
| Combined stored value bytes per user     | 200&nbsp;KiB |
| Combined stored env-injected value bytes | 24&nbsp;KiB  |
| Per-secret value bytes                   | 24&nbsp;KiB  |
| Env var name length                      | 256 bytes    |

Only secrets created with `--env` count against the env-injected budget.
Coder injects these into the workspace agent's process environment, which on Windows has a ~32&nbsp;KiB total budget.
The 24&nbsp;KiB ceiling leaves room for Coder's own variables (`CODER_*`, `PATH`, `HOME`, ...) plus any template-defined env.
To inject a value larger than this budget, use `--file` instead; file secrets do not count against the env budget.

The per-secret cap matches the env aggregate cap because a value larger than
the env aggregate could never be injected successfully as an environment
variable.

These caps measure stored bytes, which is what Coder writes to the database.
In deployments with
[database encryption](../admin/security/database-encryption.md) enabled,
stored bytes exceed the raw value.

## Manage secrets from the dashboard

You can create, edit, and delete user secrets from the Coder dashboard:

1. Select your avatar in the top right.
1. Select **Account**.
1. Select **Secrets**.

From this page you can add a new secret, update an existing secret's value,
description, or environment variable and file targets, and delete secrets you
no longer need. Each row has an enable/disable toggle that controls whether
Coder injects the secret. A secret with no environment variable or file target
cannot be enabled from the dashboard; the toggle is disabled with a tooltip,
mirroring the API invariant that an enabled secret must have a target.

The rest of this guide shows the equivalent CLI commands. The same behaviors,
limits, and injection rules apply whether you manage secrets from the
dashboard or the CLI.

## Create a secret

Use `coder secret create <name>` to create a user secret. For sensitive values,
provide the value through non-interactive stdin with a pipe or redirect. This
keeps the value out of your shell history and process arguments.

### Create an environment variable secret

Use `--env` to inject a secret into your workspaces as an environment variable.
The secret is available under the environment variable name you provide. User
secret environment variables take precedence over template-defined environment
variables with the same name, including variables set with `coder_env`.

```sh
echo -n "$API_KEY" | coder secret create api-key \
  --description "API key for workspace tools" \
  --env API_KEY
```

### Create a file secret

Use `--file` to inject a secret as a file in your workspaces. File paths must
start with `~/` or `/`.

```sh
coder secret create tool-config \
  --description "Tool configuration" \
  --file ~/.config/tool/config.json \
  < ./tool-config.json
```

On Windows workspaces, prefer `~/...` paths. They resolve to your Windows
user profile directory. Paths starting with `/` are accepted but resolve
to the root of the workspace's current drive, which is template dependent.

### Create a secret with environment variable and file targets

You can inject the same secret as both an environment variable and a file:

```sh
echo -n "$TOKEN" | coder secret create service-token \
  --description "Service token for workspace tools" \
  --env SERVICE_TOKEN \
  --file ~/.config/service/token
```

### Use `--value`

You can also provide a secret value with `--value`:

```sh
coder secret create api-key \
  --value "$API_KEY" \
  --description "API key for workspace tools" \
  --env API_KEY
```

For sensitive values, prefer stdin because `--value` can expose the secret in
shell history or process arguments.

Stdin is read verbatim. If the source file ends with a trailing newline, Coder
stores that newline as part of the secret value. Use `echo -n` when you do not
want to store a trailing newline:

```sh
echo -n "$API_KEY" | coder secret create api-key --env API_KEY
```

### Import multiple secrets from a file

Use `coder secret import <file>` to create a secret for every key in a dotenv,
JSON, or YAML file. The format is inferred from the file extension. Pass `-`
to read from non-interactive stdin, which requires `--input-format`:

```sh
coder secret import ./secrets.env

coder secret import - --input-format yaml < ./secrets.yaml
```

The import is all or nothing and never overwrites existing secrets. Keys that
are valid environment variable names are injected under the same name; other
keys are imported without an environment variable target. For details, see
[`coder secret import`](../reference/cli/secret/import.md).

### Create a disabled secret

An enabled secret must set `--env`, `--file`, or both. To store a secret
without injecting it, pass `--enabled=false`. You can add a target and enable
it later with `coder secret enable`.

```sh
echo -n "$API_KEY" | coder secret create api-key --enabled=false
```

## Update a secret

Use `coder secret update` to update a secret value, description, environment
variable target, or file target. At least one of `--value`, `--description`,
`--env`, `--file`, or `--enabled` must be specified.

```sh
# Update a secret value.
echo -n "$NEW_API_KEY" | coder secret update api-key

# Change the environment variable target.
coder secret update api-key --env NEW_API_KEY

# Clear the file injection target while keeping the secret. This only
# succeeds because api-key still has an environment variable target; a
# request that clears the last target of an enabled secret is rejected.
coder secret update api-key --file ""
```

Environment variable names and file paths are unique among your own secrets.
Coder rejects an update that uses an environment variable name or file path that another of your secrets already uses.

Clearing a target frees it for your other secrets to use.
If another secret takes it, setting the original target back is rejected until you free it again.

### Enable and disable a secret

Disable a secret to stop injecting it without deleting it, then enable it again
to resume. Enabling a secret that has no target is rejected; add a target
first.

```sh
# Stop injecting a secret without deleting it.
coder secret disable api-key

# Resume injection.
coder secret enable api-key
```

## List and delete secrets

List, show, and delete your secrets with the `coder secret` CLI:

```sh
# List all of your secrets.
coder secret list

# Show a single secret by name.
coder secret list api-key

# Delete a secret you no longer need.
coder secret delete api-key
```

The list and show commands return secret metadata only. They never return the
secret value. The `coder secret list` table includes an `enabled` column so you
can see which secrets are currently injected.

See [How your secrets reach a workspace](#how-your-secrets-reach-a-workspace)
for what happens to running workspaces when you delete a secret.

## Import secrets from a file

If you keep secrets in a dotenv file, a flat JSON object, or a flat YAML
mapping, you can import the whole file instead of creating each secret
individually:

1. Go to the [**Secrets** page](#manage-secrets-from-the-dashboard) and select
   **Add secret**.
1. Drop or select a `.env`, `.json`, `.yaml`, or `.yml` file in the upload
   area. Coder imports the file as soon as you choose it.

Every key in the file becomes a secret. For example, this dotenv file creates
two secrets, `API_KEY` and `DATABASE_URL`, each injected as an environment
variable of the same name:

```sh
API_KEY=abc123
DATABASE_URL=postgres://user:pass@db.internal/app
```

In JSON and YAML files, every value must be a string. Quote numeric and
boolean values, for example `"PORT": "8080"`.

The import is all or nothing.
If any entry fails validation, conflicts with an existing secret, or exceeds a [limit](#limits), Coder cancels the import and creates no secrets.
The file must also be 1&nbsp;MiB or smaller and contain no more than 50 keys.

Keys that are not valid environment variable names, such as `MY-TOKEN` or the
reserved name `PATH`, are imported without an environment variable target.
They are not injected into workspaces until you add a valid environment
variable or file target.

To import secrets programmatically, use the
[Secrets API](../reference/api/secrets.md#import-user-secrets-from-a-file).

For full command details, see [`coder secret`](../reference/cli/secret/index.md) and
the [Secrets API reference](../reference/api/secrets.md).

---

# Administration

Source: https://coder.com/docs/admin

![Admin settings general page](../images/admin/admin-settings-general.png)

These guides contain information on managing the Coder control plane and
[authoring templates](./templates/index.md).

First time viewers looking to set up control plane access can start with the
[configuration guide](./setup/index.md). If you're a team lead looking to design
environments for your developers, check out our
[templates guides](./templates/index.md). If you are a developer using Coder, we
recommend the [user guides](../user-guides/index.md).

For automation and scripting workflows, see our [CLI](../reference/cli/index.md)
and [API](../reference/api/index.md) docs.

For any information not strictly contained in these sections, check out our
[Tutorials](../tutorials/index.md) and [FAQs](../tutorials/faqs.md).

## What is an image, template, dev container, or workspace

### Image

- A [base image](./templates/managing-templates/image-management.md) contains
  OS-level packages and utilities that the Coder workspace is built on. It can
  be an [example image](https://github.com/coder/images), custom image in your
  registry, or one from [Docker Hub](https://hub.docker.com/search). It is
  defined in each template.
- Managed by: Externally to Coder.

### Template

- [Templates](./templates/index.md) include infrastructure-level dependencies
  for the workspace. For example, a template can include Kubernetes
  PersistentVolumeClaims, Docker containers, or EC2 VMs.
- Managed by: Template administrators from within the Coder deployment.

### Startup scripts

- Agent startup scripts apply to all users of a template. This is an
  intentionally flexible area that template authors have at their disposal to
  manage the "last mile" of workspace creation.
- Managed by: Coder template administrators.

### Workspace

- A [workspace](../user-guides/workspace-management.md) is the environment that
  a developer works in. Developers on a team each work from their own workspace
  and can use [multiple IDEs](../user-guides/workspace-access/index.md).
- Managed by: Developers

### Development containers (dev containers)

- A
  [Development Container](./integrations/devcontainers/index.md)
  is an open-source specification for defining development environments (called
  dev containers). It is generally stored in VCS alongside associated source
  code. It can reference an existing base image, or a custom Dockerfile that
  will be built on-demand.
- Managed by: Dev Teams

### Dotfiles / personalization

- Users may have their own specific preferences relating to shell prompt, custom
  keybindings, color schemes, and more. Users can leverage Coder's
  [dotfiles support](../user-guides/workspace-dotfiles.md) or create their own
  script to personalize their workspace. Be aware that users with root
  permissions in their workspace can override almost all of the previous
  configuration.
- Managed by: Individual Users

<children></children>

---

# Configure control plane access

Source: https://coder.com/docs/admin/setup

The control plane's primary configuration is done via environment variables. For
a full list of the options, run `coder server --help` or see our
[CLI documentation](../../reference/cli/server/index.md).

> [!TIP]
> Need to look up an exact environment variable, CLI flag, or YAML key for a
> setting? See the [configuration reference](./configuration-reference.md) for
> a searchable list of every option.

## Access URL

`CODER_ACCESS_URL` is required if you are not using the tunnel. Set this to the
external URL that users and workspaces use to connect to Coder (e.g.
<https://coder.example.com>). This should not be localhost.

Access URL should be an external IP address or domain with DNS records pointing to Coder.

### Tunnel

If an access URL is not specified, Coder will create a publicly accessible URL
to reverse proxy your deployment for simple setup.

## Address

You can change which port(s) Coder listens on.

```sh
# Listen on port 80
export CODER_HTTP_ADDRESS=0.0.0.0:80

# Enable TLS and listen on port 443)
export CODER_TLS_ENABLE=true
export CODER_TLS_ADDRESS=0.0.0.0:443

## Redirect from HTTP to HTTPS
export CODER_REDIRECT_TO_ACCESS_URL=true

# Start the control plane
coder server
```

## Wildcard access URL

> [!TIP]
> Learn more about the [importance and benefits of wildcard access URLs](../networking/wildcard-access-url.md)

`CODER_WILDCARD_ACCESS_URL` is necessary for [port forwarding](../networking/port-forwarding.md#dashboard) via the dashboard or running [coder_apps](../templates/index.md) on an absolute path.
Set it to a wildcard hostname that resolves to Coder, such as `*.coder.example.com` or `*-coder.example.com`.
The suffix form creates application hostnames such as `8080--main--myworkspace--john-coder.example.com`.
It requires a DNS record and TLS certificate for `*.example.com`.

> [!NOTE]
> We do not recommend using a top-level-domain for Coder wildcard access
> (for example `*.workspaces`), even on private networks with split-DNS. Some
> browsers consider these "public" domains and will refuse Coder's cookies,
> which are vital to the proper operation of this feature.

If you are providing TLS certificates directly to the control plane, either

1. Use a single certificate and key for both the root and wildcard domains.
1. Configure multiple certificates and keys via
   [`coder.tls.secretNames`](../../../helm/coder/values.yaml)
   in the Helm Chart, or
   [`--tls-cert-file`](../../reference/cli/server/index.md#--tls-cert-file) and
   [`--tls-key-file`](../../reference/cli/server/index.md#--tls-key-file) command line
   options (these both take a comma separated list of files; list certificates
   and their respective keys in the same order).

After you enable the wildcard access URL, you should [disable path-based apps](../../tutorials/best-practices/security-best-practices.md#disable-path-based-apps) for security.

## TLS & Reverse Proxy

The control plane can directly use TLS certificates with `CODER_TLS_ENABLE` and
accompanying configuration flags. However, Coder can also run behind a
reverse-proxy to terminate TLS certificates from LetsEncrypt.

- [Apache](../../tutorials/reverse-proxy-apache.md)
- [Caddy](../../tutorials/reverse-proxy-caddy.md)
- [NGINX](../../tutorials/reverse-proxy-nginx.md)

### Kubernetes TLS configuration

Below are the steps to configure Coder to terminate TLS when running on
Kubernetes. You must have the certificate `.key` and `.crt` files in your
working directory prior to step 1.

1. Create the TLS secret in your Kubernetes cluster

   ```sh
   kubectl create secret tls coder-tls -n <coder-namespace> --key="tls.key" --cert="tls.crt"
   ```

   You can use a single certificate for the both the access URL and wildcard access URL. The certificate CN must match the wildcard domain, such as `*.example.coder.com`.

1. Reference the TLS secret in your Coder Helm chart values

   ```yaml
   coder:
     tls:
       secretNames:
         - coder-tls

     # Alternatively, if you use an Ingress controller to terminate TLS,
     # set the following values:
     ingress:
       enable: true
       tls:
         enable: true
         secretName: coder-tls
         wildcardSecretName: coder-tls
   ```

## PostgreSQL Database

Coder uses a PostgreSQL database to store users, workspace metadata, and other
deployment information. Use `CODER_PG_CONNECTION_URL` to set the database that
Coder connects to. If unset, PostgreSQL binaries will be downloaded from Maven
(<https://repo1.maven.org/maven2>) and store all data in the config root.

> [!NOTE]
> Postgres 13 is the minimum supported version.

If you are using the built-in PostgreSQL deployment and need to use `psql` (aka
the PostgreSQL interactive terminal), output the connection URL with the
following command:

```console
$ coder server postgres-builtin-url
psql "postgres://coder@localhost:49627/coder?sslmode=disable&password=feU...yI1"
```

<a id="migrating-from-the-built-in-database-to-an-external-database"></a>

### Migrate from the built-in database to an external database

To migrate from the built-in database to an external database, follow these
steps:

1. Stop your Coder deployment.
1. Run `coder server postgres-builtin-serve` in a background terminal.
1. Run `coder server postgres-builtin-url` and copy its output command.
1. Run `pg_dump <built-in-connection-string> > coder.sql` to dump the internal
   database to a file.
1. Restore that content to an external database with
   `psql <external-connection-string> < coder.sql`.
1. Start your Coder deployment with
   `CODER_PG_CONNECTION_URL=<external-connection-string>`.

<a id="configuring-coder-behind-a-proxy"></a>

## Configure Coder behind a proxy

To configure Coder behind a corporate proxy, set the environment variables
`HTTP_PROXY` and `HTTPS_PROXY`. Be sure to restart the control plane. Lowercase
values (e.g. `http_proxy`) are also respected in this case.

## Continue your setup with external authentication

Coder supports external authentication via OAuth2.0. This allows enabling
integrations with Git providers, such as GitHub, GitLab, and Bitbucket.

External authentication can also be used to integrate with external services
like JFrog Artifactory and others.

Please refer to the [external authentication](../external-auth/index.md) section for
more information.

## Up Next

- [Setup and manage templates](../templates/index.md)
- [Setup external provisioners](../../install/operate/provisioners/index.md)

---

# Appearance (Premium)

Source: https://coder.com/docs/admin/setup/appearance

> [!NOTE]
> Customizing Coder's appearance is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Customize the look of your Coder deployment to meet your enterprise
requirements.

You can access the Appearance settings by navigating to
`Deployment > Appearance`.

![application name and logo url](../../images/admin/setup/appearance/application-name-logo-url.png)

## Application Name

Specify a custom application name to be displayed on the login page. The default
is Coder.

## Logo URL

Specify a custom URL for your enterprise's logo to be displayed on the sign in
page and in the top left corner of the dashboard. The default is the Coder logo.

## Announcement Banners

![announcement banner](../../images/admin/setup/appearance/announcement_banner_settings.png)

Announcement Banners let admins post important messages to all site users. Only
Site Owners may set the announcement banners.

Example: Use multiple announcement banners for concurrent deployment-wide
updates, such as maintenance or new feature rollout.

![Multiple announcements](../../images/admin/setup/appearance/multiple-banners.png)

Example: Adhere to government network classification requirements and notify
users of which network their Coder deployment is on.

![service banner secret](../../images/admin/setup/appearance/service-banner-secret.png)

## OIDC Login Button Customization

[Use environment variables to customize](../users/oidc-auth/index.md#oidc-login-customization)
the text and icon on the OIDC button on the Sign In page.

## Support Links

Support links let admins adjust the user dropdown menu to include links
referring to internal company resources. The menu section replaces the original
menu positions: documentation, report a bug to GitHub, or join the Discord
server.

![support links](../../images/admin/setup/appearance/support-links.png)

### Icons

The link icons are optional, and can be set to any url or
[builtin icon](../templates/extending-templates/icons.md#bundled-icons),
additionally `bug`, `chat`, `docs`, and `star` are available as special icons.

### Location

The `location` property is optional and determines where the support link will
be displayed:

- `navbar` - displays the link as a button in the top navigation bar
- `dropdown` - displays the link in the user dropdown menu (default)

If the `location` property is not specified, the link will be displayed in the
user dropdown menu.

### Configuration

#### Kubernetes

To configure support links in your Coder Kubernetes deployment, update your Helm
chart values as follows:

```yaml
coder:
  env:
    - name: CODER_SUPPORT_LINKS
      value: >
        [{"name": "Hello GitHub", "target": "https://github.com/coder/coder",
        "icon": "bug"},
         {"name": "Hello Slack", "target":
        "https://codercom.slack.com/archives/C014JH42DBJ", "icon":
        "/icon/slack.svg"},
         {"name": "Hello Discord", "target": "https://discord.gg/coder", "icon":
        "/icon/discord.svg", "location": "navbar"},
         {"name": "Hello Foobar", "target": "https://foo.com/bar", "icon":
        "/emojis/1f3e1.png"}]
```

#### System package

if running as a system service, set an environment variable
`CODER_SUPPORT_LINKS` in `/etc/coder.d/coder.env` as follows,

```dotenv
CODER_SUPPORT_LINKS='[{"name": "Hello GitHub", "target": "https://github.com/coder/coder", "icon": "bug"}, {"name": "Hello Slack", "target": "https://codercom.slack.com/archives/C014JH42DBJ", "icon": "https://raw.githubusercontent.com/coder/coder/main/site/static/icon/slack.svg"}, {"name": "Hello Discord", "target": "https://discord.gg/coder", "icon": "https://raw.githubusercontent.com/coder/coder/main/site/static/icon/discord.svg", "location": "navbar"}, {"name": "Hello Foobar", "target": "https://discord.gg/coder", "icon": "/emojis/1f3e1.png"}]'
```

For CLI, use,

```sh
export CODER_SUPPORT_LINKS='[{"name": "Hello GitHub", "target": "https://github.com/coder/coder", "icon": "bug"}, {"name": "Hello Slack", "target": "https://codercom.slack.com/archives/C014JH42DBJ", "icon": "https://raw.githubusercontent.com/coder/coder/main/site/static/icon/slack.svg"}, {"name": "Hello Discord", "target": "https://discord.gg/coder", "icon": "https://raw.githubusercontent.com/coder/coder/main/site/static/icon/discord.svg", "location": "navbar"}, {"name": "Hello Foobar", "target": "https://discord.gg/coder", "icon": "/emojis/1f3e1.png"}]'
coder-server
```

---

# Configuration Reference

Source: https://coder.com/docs/admin/setup/configuration-reference

<!-- DO NOT EDIT | GENERATED CONTENT -->
# Configuration reference

Coder server is configured primarily through environment variables. This page
lists every option so you can search by environment variable name, CLI flag, or
YAML key. For first-time setup guidance and worked examples, see
[Configure Control Plane Access](./index.md).

Each option can be set through one or more of the methods below. An option lists
only the methods that apply to it.

- An environment variable (recommended for production deployments running as a
  system service, container, or Helm chart).
- A CLI flag passed to `coder server` (useful for one-off invocations
  and local development).
- A key in a YAML configuration file passed with `--config`.

For a full description of each option's accepted values and behavior, follow the
flag link into the [`coder server` CLI reference](../../reference/cli/server/index.md).

Deprecated options are listed at the end of each section.

## General

### Cache directory

The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd. This directory is NOT safe to be configured as a shared directory across coderd/provisionerd replicas.

- Environment variable: `CODER_CACHE_DIRECTORY`
- CLI flag: [`--cache-dir`](../../reference/cli/server/index.md#--cache-dir)
- YAML key: `cacheDir`
- Default value: `~/.cache/coder`

### Default OAuth refresh lifetime

The default lifetime duration for OAuth2 refresh tokens. This controls how long refresh tokens remain valid after issuance or rotation.

- Environment variable: `CODER_DEFAULT_OAUTH_REFRESH_LIFETIME`
- CLI flag: [`--default-oauth-refresh-lifetime`](../../reference/cli/server/index.md#--default-oauth-refresh-lifetime)
- YAML key: `defaultOAuthRefreshLifetime`
- Default value: `720h0m0s`

### Default token lifetime

The default lifetime duration for API tokens. This value is used when creating a token without specifying a duration, such as when authenticating the CLI or an IDE plugin.

- Environment variable: `CODER_DEFAULT_TOKEN_LIFETIME`
- CLI flag: [`--default-token-lifetime`](../../reference/cli/server/index.md#--default-token-lifetime)
- YAML key: `defaultTokenLifetime`
- Default value: `168h0m0s`

### Disable chat caller-supplied tools

Disable caller-supplied tools in chats. Chat requests that include unsafe_dynamic_tools or inline_mcp_servers are rejected, and existing chats run without their dynamic tools and inline MCP servers.

- Environment variable: `CODER_DISABLE_CHAT_CALLER_SUPPLIED_TOOLS`
- CLI flag: [`--disable-chat-caller-supplied-tools`](../../reference/cli/server/index.md#--disable-chat-caller-supplied-tools)
- YAML key: `disableChatCallerSuppliedTools`

### Disable chat sharing

Disable chat sharing. Chat ACL checking is disabled and only owners can access their chats.

- Environment variable: `CODER_DISABLE_CHAT_SHARING`
- CLI flag: [`--disable-chat-sharing`](../../reference/cli/server/index.md#--disable-chat-sharing)
- YAML key: `disableChatSharing`

### Disable owner workspace access

Remove the permission for the 'owner' role to have workspace execution on all workspaces. This prevents the 'owner' from ssh, apps, and terminal access based on the 'owner' role. They still have their user permissions to access their own workspaces.

- Environment variable: `CODER_DISABLE_OWNER_WORKSPACE_ACCESS`
- CLI flag: [`--disable-owner-workspace-access`](../../reference/cli/server/index.md#--disable-owner-workspace-access)
- YAML key: `disableOwnerWorkspaceAccess`

### Disable path apps

Disable workspace apps that are not served from subdomains. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. This is recommended for security purposes if a --wildcard-access-url is configured.

- Environment variable: `CODER_DISABLE_PATH_APPS`
- CLI flag: [`--disable-path-apps`](../../reference/cli/server/index.md#--disable-path-apps)
- YAML key: `disablePathApps`

### Disable user secret file path

Disable Coder-managed file path delivery for user secrets. Stored paths remain until users clear them and resume if this setting is turned off.

- Environment variable: `CODER_DISABLE_USER_SECRET_FILE_PATH`
- CLI flag: [`--disable-user-secret-file-path`](../../reference/cli/server/index.md#--disable-user-secret-file-path)
- YAML key: `disableUserSecretFilePath`

### Disable workspace agent context sync

Stop persisting workspace agent context snapshots (instructions, skills, and MCP state used for pinned chat context). When set, coderd rejects agent context pushes as unimplemented and agents stop sending them; chats cannot pin workspace context. Use this to shed the database write load of context sync on large deployments.

- Environment variable: `CODER_DISABLE_WORKSPACE_AGENT_CONTEXT_SYNC`
- CLI flag: [`--disable-workspace-agent-context-sync`](../../reference/cli/server/index.md#--disable-workspace-agent-context-sync)
- YAML key: `disableWorkspaceAgentContextSync`

### Disable workspace sharing

Disable workspace sharing. Workspace ACL checking is disabled and only owners can have ssh, apps and terminal access to workspaces. Access based on the 'owner' role is also allowed unless disabled via --disable-owner-workspace-access.

- Environment variable: `CODER_DISABLE_WORKSPACE_SHARING`
- CLI flag: [`--disable-workspace-sharing`](../../reference/cli/server/index.md#--disable-workspace-sharing)
- YAML key: `disableWorkspaceSharing`

### Enable swagger endpoint

Expose the swagger endpoint via /swagger.

- Environment variable: `CODER_SWAGGER_ENABLE`
- CLI flag: [`--swagger-enable`](../../reference/cli/server/index.md#--swagger-enable)
- YAML key: `enableSwagger`

### Experiments

Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.

- Environment variable: `CODER_EXPERIMENTS`
- CLI flag: [`--experiments`](../../reference/cli/server/index.md#--experiments)
- YAML key: `experiments`

### External auth GitHub default provider enable

Enable the default GitHub external auth provider managed by Coder.

- Environment variable: `CODER_EXTERNAL_AUTH_GITHUB_DEFAULT_PROVIDER_ENABLE`
- CLI flag: [`--external-auth-github-default-provider-enable`](../../reference/cli/server/index.md#--external-auth-github-default-provider-enable)
- YAML key: `externalAuthGithubDefaultProviderEnable`
- Default value: `true`

### External token encryption keys

Encrypt OIDC and Git authentication tokens with AES-256-GCM in the database. The value must be a comma-separated list of base64-encoded keys. Each key, when base64-decoded, must be exactly 32 bytes in length. The first key will be used to encrypt new values. Subsequent keys will be used as a fallback when decrypting. During normal operation it is recommended to only set one key unless you are in the process of rotating keys with the `coder server dbcrypt rotate` command.

- Environment variable: `CODER_EXTERNAL_TOKEN_ENCRYPTION_KEYS`
- CLI flag: [`--external-token-encryption-keys`](../../reference/cli/server/index.md#--external-token-encryption-keys)

### Postgres auth

Type of auth to use when connecting to postgres. For AWS RDS, using IAM authentication (awsiamrds) is recommended.

- Environment variable: `CODER_PG_AUTH`
- CLI flag: [`--postgres-auth`](../../reference/cli/server/index.md#--postgres-auth)
- YAML key: `pgAuth`
- Default value: `password`

### Postgres connection max idle

Maximum number of idle connections to the database. Set to "auto" (the default) to use max open / 3. Value must be greater or equal to 0; 0 means explicitly no idle connections.

- Environment variable: `CODER_PG_CONN_MAX_IDLE`
- CLI flag: [`--postgres-conn-max-idle`](../../reference/cli/server/index.md#--postgres-conn-max-idle)
- YAML key: `pgConnMaxIdle`
- Default value: `auto`

### Postgres connection max open

Maximum number of open connections to the database. Defaults to 10.

- Environment variable: `CODER_PG_CONN_MAX_OPEN`
- CLI flag: [`--postgres-conn-max-open`](../../reference/cli/server/index.md#--postgres-conn-max-open)
- YAML key: `pgConnMaxOpen`
- Default value: `10`

### Postgres connection URL

URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with "coder server postgres-builtin-url". Note that any special characters in the URL must be URL-encoded.

- Environment variable: `CODER_PG_CONNECTION_URL`
- CLI flag: [`--postgres-url`](../../reference/cli/server/index.md#--postgres-url)

### SCIM API key

Enables SCIM and sets the authentication header for the built-in SCIM server. New users are automatically created with OIDC authentication.

- Environment variable: `CODER_SCIM_AUTH_HEADER`
- CLI flag: [`--scim-auth-header`](../../reference/cli/server/index.md#--scim-auth-header)

### SCIM use legacy

Use the legacy SCIM implementation instead of the SCIM 2.0 handler. This is provided for backward compatibility for existing users.

- Environment variable: `CODER_SCIM_USE_LEGACY`
- CLI flag: [`--scim-use-legacy`](../../reference/cli/server/index.md#--scim-use-legacy)
- YAML key: `scimUseLegacy`
- Default value: `true`

### SSH keygen algorithm

The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096".

- Environment variable: `CODER_SSH_KEYGEN_ALGORITHM`
- CLI flag: [`--ssh-keygen-algorithm`](../../reference/cli/server/index.md#--ssh-keygen-algorithm)
- YAML key: `sshKeygenAlgorithm`
- Default value: `ed25519`

### Support links

Support links to display in the top right drop down menu.

- Environment variable: `CODER_SUPPORT_LINKS`
- CLI flag: [`--support-links`](../../reference/cli/server/index.md#--support-links)
- YAML key: `supportLinks`

### Terms of service URL

A URL to an external Terms of Service that must be accepted by users when logging in.

- Environment variable: `CODER_TERMS_OF_SERVICE_URL`
- CLI flag: [`--terms-of-service-url`](../../reference/cli/server/index.md#--terms-of-service-url)
- YAML key: `termsOfServiceURL`

### Update check

Periodically check for new releases of Coder and inform the owner. The check is performed once per day.

- Environment variable: `CODER_UPDATE_CHECK`
- CLI flag: [`--update-check`](../../reference/cli/server/index.md#--update-check)
- YAML key: `updateCheck`
- Default value: `false`

## AI Gateway

### AI budget period

Determines when accumulated AI spend resets to zero, aligned to UTC calendar boundaries. Only "month" is currently supported.

- Environment variable: `CODER_AI_BUDGET_PERIOD`
- CLI flag: [`--ai-budget-period`](../../reference/cli/server/index.md#--ai-budget-period)
- YAML key: `ai_gateway.budget_period`
- Default value: `month`

### AI budget policy

Determines the effective group when a user belongs to multiple groups with AI budgets. "highest" selects the group with the largest spend limit, and is currently the only supported value.

- Environment variable: `CODER_AI_BUDGET_POLICY`
- CLI flag: [`--ai-budget-policy`](../../reference/cli/server/index.md#--ai-budget-policy)
- YAML key: `ai_gateway.budget_policy`
- Default value: `highest`

### API dump directory

Base directory for dumping AI Gateway request/response pairs to disk for debugging. When set, each provider writes under a subdirectory named after the provider. Sensitive headers are redacted. Leave empty to disable.

- Environment variable: `CODER_AI_GATEWAY_DUMP_DIR`
- CLI flag: [`--ai-gateway-dump-dir`](../../reference/cli/server/index.md#--ai-gateway-dump-dir)
- YAML key: `ai_gateway.api_dump_dir`

### Actor header email

Header name for the authenticated user's email address. Empty disables this header. Requires AI Gateway actor headers to be enabled. Applies to every configured provider; email is personal information.

- Environment variable: `CODER_AI_GATEWAY_ACTOR_HEADER_EMAIL`
- CLI flag: [`--ai-gateway-actor-header-email`](../../reference/cli/server/index.md#--ai-gateway-actor-header-email)
- YAML key: `ai_gateway.actor_header_email`

### Actor header ID

Header name for the authenticated user's ID. Empty disables this header. Requires AI Gateway actor headers to be enabled.

- Environment variable: `CODER_AI_GATEWAY_ACTOR_HEADER_ID`
- CLI flag: [`--ai-gateway-actor-header-id`](../../reference/cli/server/index.md#--ai-gateway-actor-header-id)
- YAML key: `ai_gateway.actor_header_id`
- Default value: `X-AI-Bridge-Actor-ID`

### Actor header username

Header name for the authenticated user's username. Empty disables this header. Requires AI Gateway actor headers to be enabled.

- Environment variable: `CODER_AI_GATEWAY_ACTOR_HEADER_USERNAME`
- CLI flag: [`--ai-gateway-actor-header-username`](../../reference/cli/server/index.md#--ai-gateway-actor-header-username)
- YAML key: `ai_gateway.actor_header_username`
- Default value: `X-AI-Bridge-Actor-Metadata-Username`

### Allow BYOK

Allow users to provide their own LLM API keys or subscriptions. When disabled, only centralized key authentication is permitted.

- Environment variable: `CODER_AI_GATEWAY_ALLOW_BYOK`
- CLI flag: [`--ai-gateway-allow-byok`](../../reference/cli/server/index.md#--ai-gateway-allow-byok)
- YAML key: `ai_gateway.allow_byok`
- Default value: `true`

### Circuit breaker enabled

Enable the circuit breaker to protect against cascading failures from upstream AI provider overload (503, 529).

- Environment variable: `CODER_AI_GATEWAY_CIRCUIT_BREAKER_ENABLED`
- CLI flag: [`--ai-gateway-circuit-breaker-enabled`](../../reference/cli/server/index.md#--ai-gateway-circuit-breaker-enabled)
- YAML key: `ai_gateway.circuit_breaker_enabled`
- Default value: `false`

### Data retention duration

Length of time to retain data such as interceptions and all related records (token, prompt, tool use).

- Environment variable: `CODER_AI_GATEWAY_RETENTION`
- CLI flag: [`--ai-gateway-retention`](../../reference/cli/server/index.md#--ai-gateway-retention)
- YAML key: `ai_gateway.retention`
- Default value: `60d`

### Disable content recording

Stop recording the content of intercepted conversations. No user prompt, tool call or model reasoning record is stored, including tool names and the arguments they were called with. Interceptions and token usage are still recorded, so cost controls, budget enforcement and spend reporting are unaffected. Sessions show no conversation detail, prompt and tool call telemetry report zero, and interceptions are no longer grouped into threads for clients that do not send their own session ID. Combine with --ai-gateway-structured-logging-source=gateway to keep exporting these records to a SIEM instead.

- Environment variable: `CODER_AI_GATEWAY_DISABLE_CONTENT_RECORDING`
- CLI flag: [`--ai-gateway-disable-content-recording`](../../reference/cli/server/index.md#--ai-gateway-disable-content-recording)
- YAML key: `ai_gateway.disable_content_recording`
- Default value: `false`

### Enabled

Whether to start an in-memory AI Gateway instance.

- Environment variable: `CODER_AI_GATEWAY_ENABLED`
- CLI flag: [`--ai-gateway-enabled`](../../reference/cli/server/index.md#--ai-gateway-enabled)
- YAML key: `ai_gateway.enabled`
- Default value: `true`

### Max concurrency

Maximum number of concurrent AI Gateway requests per replica. Set to 0 to disable (unlimited).

- Environment variable: `CODER_AI_GATEWAY_MAX_CONCURRENCY`
- CLI flag: [`--ai-gateway-max-concurrency`](../../reference/cli/server/index.md#--ai-gateway-max-concurrency)
- YAML key: `ai_gateway.max_concurrency`
- Default value: `0`

### Rate limit

Maximum number of AI Gateway requests per second per replica. Set to 0 to disable (unlimited).

- Environment variable: `CODER_AI_GATEWAY_RATE_LIMIT`
- CLI flag: [`--ai-gateway-rate-limit`](../../reference/cli/server/index.md#--ai-gateway-rate-limit)
- YAML key: `ai_gateway.rate_limit`
- Default value: `0`

### Send actor headers

Add configured headers identifying the authenticated user to intercepted upstream requests. Use this when a proxy between AI Gateway and an upstream AI provider needs user identity. When enabled, removes client-supplied headers at configured actor-header destinations before adding authenticated values. Client headers starting with X-AI-Bridge-Actor are always removed.

- Environment variable: `CODER_AI_GATEWAY_SEND_ACTOR_HEADERS`
- CLI flag: [`--ai-gateway-send-actor-headers`](../../reference/cli/server/index.md#--ai-gateway-send-actor-headers)
- YAML key: `ai_gateway.send_actor_headers`
- Default value: `false`

### Structured logging

Emit structured logs for AI Gateway interception records. Use this for exporting these records to external SIEM or observability systems.

- Environment variable: `CODER_AI_GATEWAY_STRUCTURED_LOGGING`
- CLI flag: [`--ai-gateway-structured-logging`](../../reference/cli/server/index.md#--ai-gateway-structured-logging)
- YAML key: `ai_gateway.structured_logging`
- Default value: `false`

### Structured logging source

Which process emits AI Gateway interception records when structured logging is enabled: coderd, the gateway, or both. The gateway emits records that are never persisted, such as those dropped by --ai-gateway-disable-content-recording, but cannot report thread_parent_id or thread_root_id. Use both to verify a move from one to the other; records reaching coderd are then reported twice. A standalone gateway must be configured to emit its own records, and its logs shipped rather than coderd's.

- Environment variable: `CODER_AI_GATEWAY_STRUCTURED_LOGGING_SOURCE`
- CLI flag: [`--ai-gateway-structured-logging-source`](../../reference/cli/server/index.md#--ai-gateway-structured-logging-source)
- YAML key: `ai_gateway.structured_logging_source`
- Default value: `coderd`

## AI Gateway Proxy

### API dump directory

Directory for dumping MITM request/response pairs to disk for debugging. When set, each proxied request produces .req.txt and .resp.txt files organized by provider. Sensitive headers are redacted. Leave empty to disable.

- Environment variable: `CODER_AI_GATEWAY_PROXY_DUMP_DIR`
- CLI flag: [`--ai-gateway-proxy-dump-dir`](../../reference/cli/server/index.md#--ai-gateway-proxy-dump-dir)
- YAML key: `ai_gateway_proxy.api_dump_dir`

### Allowed private CIDRs

Comma-separated list of CIDR ranges that are permitted even though they fall within blocked private/reserved IP ranges. By default all private ranges are blocked to prevent SSRF attacks. Use this to allow access to specific internal networks.

- Environment variable: `CODER_AI_GATEWAY_PROXY_ALLOWED_PRIVATE_CIDRS`
- CLI flag: [`--ai-gateway-proxy-allowed-private-cidrs`](../../reference/cli/server/index.md#--ai-gateway-proxy-allowed-private-cidrs)
- YAML key: `ai_gateway_proxy.allowed_private_cidrs`

### Enabled

Enable the AI Gateway MITM Proxy for intercepting and decrypting AI provider requests.

- Environment variable: `CODER_AI_GATEWAY_PROXY_ENABLED`
- CLI flag: [`--ai-gateway-proxy-enabled`](../../reference/cli/server/index.md#--ai-gateway-proxy-enabled)
- YAML key: `ai_gateway_proxy.enabled`
- Default value: `false`

### Listen address

The address the AI Gateway Proxy will listen on.

- Environment variable: `CODER_AI_GATEWAY_PROXY_LISTEN_ADDR`
- CLI flag: [`--ai-gateway-proxy-listen-addr`](../../reference/cli/server/index.md#--ai-gateway-proxy-listen-addr)
- YAML key: `ai_gateway_proxy.listen_addr`
- Default value: `:8888`

### MITM CA certificate file

Path to the CA certificate file used to intercept (MITM) HTTPS traffic from AI clients. This CA must be trusted by AI clients for the proxy to decrypt their requests.

- Environment variable: `CODER_AI_GATEWAY_PROXY_CERT_FILE`
- CLI flag: [`--ai-gateway-proxy-cert-file`](../../reference/cli/server/index.md#--ai-gateway-proxy-cert-file)
- YAML key: `ai_gateway_proxy.cert_file`

### MITM CA key file

Path to the CA private key file used to intercept (MITM) HTTPS traffic from AI clients.

- Environment variable: `CODER_AI_GATEWAY_PROXY_KEY_FILE`
- CLI flag: [`--ai-gateway-proxy-key-file`](../../reference/cli/server/index.md#--ai-gateway-proxy-key-file)
- YAML key: `ai_gateway_proxy.key_file`

### TLS certificate file

Path to the TLS certificate file for the AI Gateway Proxy listener. Must be set together with AI Gateway Proxy TLS Key File.

- Environment variable: `CODER_AI_GATEWAY_PROXY_TLS_CERT_FILE`
- CLI flag: [`--ai-gateway-proxy-tls-cert-file`](../../reference/cli/server/index.md#--ai-gateway-proxy-tls-cert-file)
- YAML key: `ai_gateway_proxy.tls_cert_file`

### TLS key file

Path to the TLS private key file for the AI Gateway Proxy listener. Must be set together with AI Gateway Proxy TLS Certificate File.

- Environment variable: `CODER_AI_GATEWAY_PROXY_TLS_KEY_FILE`
- CLI flag: [`--ai-gateway-proxy-tls-key-file`](../../reference/cli/server/index.md#--ai-gateway-proxy-tls-key-file)
- YAML key: `ai_gateway_proxy.tls_key_file`

### Target

Base URL of the AI Gateway to forward intercepted requests to. Defaults to the embedded AI Gateway address at the Coder access URL plus /api/v2/ai-gateway.

- Environment variable: `CODER_AI_GATEWAY_PROXY_TARGET`
- CLI flag: [`--ai-gateway-proxy-target`](../../reference/cli/server/index.md#--ai-gateway-proxy-target)
- YAML key: `ai_gateway_proxy.target`

### Upstream proxy

URL of an upstream HTTP proxy to chain tunneled (non-allowlisted) requests through. Format: http://[user:pass@]host:port or https://[user:pass@]host:port.

- Environment variable: `CODER_AI_GATEWAY_PROXY_UPSTREAM`
- CLI flag: [`--ai-gateway-proxy-upstream`](../../reference/cli/server/index.md#--ai-gateway-proxy-upstream)
- YAML key: `ai_gateway_proxy.upstream_proxy`

### Upstream proxy CA

Path to a PEM-encoded CA certificate to trust for the upstream proxy's TLS connection. Only needed for HTTPS upstream proxies with certificates not trusted by the system. If not provided, the system certificate pool is used.

- Environment variable: `CODER_AI_GATEWAY_PROXY_UPSTREAM_CA`
- CLI flag: [`--ai-gateway-proxy-upstream-ca`](../../reference/cli/server/index.md#--ai-gateway-proxy-upstream-ca)
- YAML key: `ai_gateway_proxy.upstream_proxy_ca`

## Chat

Configure the background chat processing daemon.

### Debug logging enabled

Force chat debug logging on for every chat, bypassing the runtime admin and user opt-in settings.

- Environment variable: `CODER_CHAT_DEBUG_LOGGING_ENABLED`
- CLI flag: [`--chat-debug-logging-enabled`](../../reference/cli/server/index.md#--chat-debug-logging-enabled)
- YAML key: `chat.debugLoggingEnabled`
- Default value: `false`

### Max attachments per chat

Maximum number of files linked to a chat, including user uploads, files the agent attaches, and desktop recordings and their thumbnails. Linking a file beyond the limit permanently deletes the chat's earliest-uploaded files, and earlier messages show them as expired. A message that includes more files than the limit is rejected with HTTP 400. Must be at least 1.

- Environment variable: `CODER_CHAT_MAX_ATTACHMENTS_PER_CHAT`
- CLI flag: [`--chat-max-attachments-per-chat`](../../reference/cli/server/index.md#--chat-max-attachments-per-chat)
- YAML key: `chat.maxAttachmentsPerChat`
- Default value: `50`

### Max concurrent recording uploads

Maximum number of virtual desktop recordings that each Coder server stores at the same time. Each upload holds the recording and its thumbnail in memory, up to 110 MB. Additional recordings wait for a free slot and are discarded if none frees up within 90 seconds. Must be at least 1.

- Environment variable: `CODER_CHAT_MAX_CONCURRENT_RECORDING_UPLOADS`
- CLI flag: [`--chat-max-concurrent-recording-uploads`](../../reference/cli/server/index.md#--chat-max-concurrent-recording-uploads)
- YAML key: `chat.maxConcurrentRecordingUploads`
- Default value: `25`

### Max generation retries

Maximum number of consecutive retries after a model generation fails with a transient error, such as a rate limit, an overloaded provider, or a stream that stops sending data. The count resets after each successful step. When the retries run out, the chat moves to the error state and shows the provider error. Advisor calls and the generation of chat titles, summaries, and turn status labels use the same limit. Must be at least 1.

- Environment variable: `CODER_CHAT_MAX_GENERATION_RETRIES`
- CLI flag: [`--chat-max-generation-retries`](../../reference/cli/server/index.md#--chat-max-generation-retries)
- YAML key: `chat.maxGenerationRetries`
- Default value: `25`

### Max prompt bytes

Maximum size in bytes of the deployment system prompt, the plan mode instructions, and each user's custom prompt. Saving a longer prompt fails with HTTP 400. Lowering the limit does not affect prompts that are already saved. Must be at least 1.

- Environment variable: `CODER_CHAT_MAX_PROMPT_BYTES`
- CLI flag: [`--chat-max-prompt-bytes`](../../reference/cli/server/index.md#--chat-max-prompt-bytes)
- YAML key: `chat.maxPromptBytes`
- Default value: `131072`

### Max queued messages per chat

Maximum number of messages that can be queued in a chat. Sending a message to a chat whose queue is full fails with HTTP 429. Must be at least 1.

- Environment variable: `CODER_CHAT_MAX_QUEUED_MESSAGES_PER_CHAT`
- CLI flag: [`--chat-max-queued-messages-per-chat`](../../reference/cli/server/index.md#--chat-max-queued-messages-per-chat)
- YAML key: `chat.maxQueuedMessagesPerChat`
- Default value: `20`

### Max steps per turn

Maximum number of steps in a chat turn. Each model response is one step; compaction summaries, advisor calls, and retried attempts do not count. A turn that reaches the limit runs the tools from the last response, then ends without an error. Must be at least 1.

- Environment variable: `CODER_CHAT_MAX_STEPS_PER_TURN`
- CLI flag: [`--chat-max-steps-per-turn`](../../reference/cli/server/index.md#--chat-max-steps-per-turn)
- YAML key: `chat.maxStepsPerTurn`
- Default value: `1200`

### Stream silence timeout

Maximum time to wait for the next streamed part from the chat model before the attempt is canceled and retried. This also bounds the time to first token. Set to 0 to disable. Must be no more than 24h.

- Environment variable: `CODER_CHAT_STREAM_SILENCE_TIMEOUT`
- CLI flag: [`--chat-stream-silence-timeout`](../../reference/cli/server/index.md#--chat-stream-silence-timeout)
- YAML key: `chat.streamSilenceTimeout`
- Default value: `10m0s`

## Client

These options change the behavior of how clients interact with the Coder. Clients include the Coder CLI, Coder Desktop, IDE extensions, and the web UI.

### CLI upgrade message

The upgrade message to display to users when a client/server mismatch is detected. By default it instructs users to update using 'curl -fsSL https://coder.com/install.sh | sh'.

- Environment variable: `CODER_CLI_UPGRADE_MESSAGE`
- CLI flag: [`--cli-upgrade-message`](../../reference/cli/server/index.md#--cli-upgrade-message)
- YAML key: `client.cliUpgradeMessage`

### SSH config options

These SSH config options will override the default SSH config options. Provide options in "key=value" or "key value" format separated by commas. Using this incorrectly can break SSH to your deployment, use cautiously. The following options are not allowed: Host, Match, Include, ProxyCommand, ProxyJump, LocalCommand, PermitLocalCommand, RemoteCommand, KnownHostsCommand, PKCS11Provider, SecurityKeyProvider, SmartcardDevice, XAuthLocation. Option values must not contain newline, carriage return, or NUL characters.

- Environment variable: `CODER_SSH_CONFIG_OPTIONS`
- CLI flag: [`--ssh-config-options`](../../reference/cli/server/index.md#--ssh-config-options)
- YAML key: `client.sshConfigOptions`

### Web terminal renderer

The renderer to use when opening a web terminal. Valid values are 'canvas', 'webgl', or 'dom'.

- Environment variable: `CODER_WEB_TERMINAL_RENDERER`
- CLI flag: [`--web-terminal-renderer`](../../reference/cli/server/index.md#--web-terminal-renderer)
- YAML key: `client.webTerminalRenderer`
- Default value: `canvas`

### Workspace hostname suffix

Workspace hostnames use this suffix in SSH config and Coder Connect on Coder Desktop. By default it is coder, resulting in names like myworkspace.coder. The suffix must not start with a dot, and must not contain spaces, newlines, or glob characters (* and ?).

- Environment variable: `CODER_WORKSPACE_HOSTNAME_SUFFIX`
- CLI flag: [`--workspace-hostname-suffix`](../../reference/cli/server/index.md#--workspace-hostname-suffix)
- YAML key: `client.workspaceHostnameSuffix`
- Default value: `coder`

## Config

Use a YAML configuration file when your server launch become unwieldy.

### Path

Specify a YAML file to load configuration from.

- Environment variable: `CODER_CONFIG_PATH`
- CLI flag: [`--config`](../../reference/cli/server/index.md#-c---config)

### Write config

Write out the current server config as YAML to stdout.

- CLI flag: [`--write-config`](../../reference/cli/server/index.md#--write-config)

## Email

Configure how emails are sent.

### Force TLS

Force a TLS connection to the configured SMTP smarthost.

- Environment variable: `CODER_EMAIL_FORCE_TLS`
- CLI flag: [`--email-force-tls`](../../reference/cli/server/index.md#--email-force-tls)
- YAML key: `email.forceTLS`
- Default value: `false`

### From address

The sender's address to use.

- Environment variable: `CODER_EMAIL_FROM`
- CLI flag: [`--email-from`](../../reference/cli/server/index.md#--email-from)
- YAML key: `email.from`

### Hello

The hostname identifying the SMTP server.

- Environment variable: `CODER_EMAIL_HELLO`
- CLI flag: [`--email-hello`](../../reference/cli/server/index.md#--email-hello)
- YAML key: `email.hello`
- Default value: `localhost`

### Smarthost

The intermediary SMTP host through which emails are sent.

- Environment variable: `CODER_EMAIL_SMARTHOST`
- CLI flag: [`--email-smarthost`](../../reference/cli/server/index.md#--email-smarthost)
- YAML key: `email.smarthost`

### Email authentication

Configure SMTP authentication options.

#### Identity

Identity to use with PLAIN authentication.

- Environment variable: `CODER_EMAIL_AUTH_IDENTITY`
- CLI flag: [`--email-auth-identity`](../../reference/cli/server/index.md#--email-auth-identity)
- YAML key: `email.emailAuth.identity`

#### Password

Password to use with PLAIN/LOGIN authentication.

- Environment variable: `CODER_EMAIL_AUTH_PASSWORD`
- CLI flag: [`--email-auth-password`](../../reference/cli/server/index.md#--email-auth-password)

#### Password file

File from which to load password for use with PLAIN/LOGIN authentication.

- Environment variable: `CODER_EMAIL_AUTH_PASSWORD_FILE`
- CLI flag: [`--email-auth-password-file`](../../reference/cli/server/index.md#--email-auth-password-file)
- YAML key: `email.emailAuth.passwordFile`

#### Username

Username to use with PLAIN/LOGIN authentication.

- Environment variable: `CODER_EMAIL_AUTH_USERNAME`
- CLI flag: [`--email-auth-username`](../../reference/cli/server/index.md#--email-auth-username)
- YAML key: `email.emailAuth.username`

### Email TLS

Configure TLS for your SMTP server target.

#### Certificate authority file

CA certificate file to use.

- Environment variable: `CODER_EMAIL_TLS_CACERTFILE`
- CLI flag: [`--email-tls-ca-cert-file`](../../reference/cli/server/index.md#--email-tls-ca-cert-file)
- YAML key: `email.emailTLS.caCertFile`

#### Certificate file

Certificate file to use.

- Environment variable: `CODER_EMAIL_TLS_CERTFILE`
- CLI flag: [`--email-tls-cert-file`](../../reference/cli/server/index.md#--email-tls-cert-file)
- YAML key: `email.emailTLS.certFile`

#### Certificate key file

Certificate key file to use.

- Environment variable: `CODER_EMAIL_TLS_CERTKEYFILE`
- CLI flag: [`--email-tls-cert-key-file`](../../reference/cli/server/index.md#--email-tls-cert-key-file)
- YAML key: `email.emailTLS.certKeyFile`

#### Server name

Server name to verify against the target certificate.

- Environment variable: `CODER_EMAIL_TLS_SERVERNAME`
- CLI flag: [`--email-tls-server-name`](../../reference/cli/server/index.md#--email-tls-server-name)
- YAML key: `email.emailTLS.serverName`

#### Skip certificate verification (insecure)

Skip verification of the target server's certificate (insecure).

- Environment variable: `CODER_EMAIL_TLS_SKIPVERIFY`
- CLI flag: [`--email-tls-skip-verify`](../../reference/cli/server/index.md#--email-tls-skip-verify)
- YAML key: `email.emailTLS.insecureSkipVerify`

#### StartTLS

Enable STARTTLS to upgrade insecure SMTP connections using TLS.

- Environment variable: `CODER_EMAIL_TLS_STARTTLS`
- CLI flag: [`--email-tls-starttls`](../../reference/cli/server/index.md#--email-tls-starttls)
- YAML key: `email.emailTLS.startTLS`

## Introspection

Configure logging, tracing, stat collection, and metrics exporting.

### Health check

#### Refresh

Refresh interval for healthchecks.

- Environment variable: `CODER_HEALTH_CHECK_REFRESH`
- CLI flag: [`--health-check-refresh`](../../reference/cli/server/index.md#--health-check-refresh)
- YAML key: `introspection.healthcheck.refresh`
- Default value: `10m0s`

#### Threshold: database

The threshold for the database health check. If the median latency of the database exceeds this threshold over 5 attempts, the database is considered unhealthy. The default value is 15ms.

- Environment variable: `CODER_HEALTH_CHECK_THRESHOLD_DATABASE`
- CLI flag: [`--health-check-threshold-database`](../../reference/cli/server/index.md#--health-check-threshold-database)
- YAML key: `introspection.healthcheck.thresholdDatabase`
- Default value: `15ms`

### Logging

#### Enable Terraform debug mode

Allow administrators to enable Terraform debug output.

- Environment variable: `CODER_ENABLE_TERRAFORM_DEBUG_MODE`
- CLI flag: [`--enable-terraform-debug-mode`](../../reference/cli/server/index.md#--enable-terraform-debug-mode)
- YAML key: `introspection.logging.enableTerraformDebugMode`
- Default value: `false`

#### Human log location

Output human-readable logs to a given file.

- Environment variable: `CODER_LOGGING_HUMAN`
- CLI flag: [`--log-human`](../../reference/cli/server/index.md#--log-human)
- YAML key: `introspection.logging.humanPath`
- Default value: `/dev/stderr`

#### JSON log location

Output JSON logs to a given file.

- Environment variable: `CODER_LOGGING_JSON`
- CLI flag: [`--log-json`](../../reference/cli/server/index.md#--log-json)
- YAML key: `introspection.logging.jsonPath`

#### Log filter

Filter debug logs by matching against a given regex. Use .* to match all debug logs.

- Environment variable: `CODER_LOG_FILTER`
- CLI flag: [`--log-filter`](../../reference/cli/server/index.md#-l---log-filter)
- YAML key: `introspection.logging.filter`

#### Stackdriver log location

Output Stackdriver compatible logs to a given file.

- Environment variable: `CODER_LOGGING_STACKDRIVER`
- CLI flag: [`--log-stackdriver`](../../reference/cli/server/index.md#--log-stackdriver)
- YAML key: `introspection.logging.stackdriverPath`

### Prometheus

#### Address

The bind address to serve prometheus metrics.

- Environment variable: `CODER_PROMETHEUS_ADDRESS`
- CLI flag: [`--prometheus-address`](../../reference/cli/server/index.md#--prometheus-address)
- YAML key: `introspection.prometheus.address`
- Default value: `127.0.0.1:2112`

#### Aggregate agent stats by

When collecting agent stats, aggregate metrics by a given set of comma-separated labels to reduce cardinality. Accepted values are agent_name, template_name, username, workspace_name.

- Environment variable: `CODER_PROMETHEUS_AGGREGATE_AGENT_STATS_BY`
- CLI flag: [`--prometheus-aggregate-agent-stats-by`](../../reference/cli/server/index.md#--prometheus-aggregate-agent-stats-by)
- YAML key: `introspection.prometheus.aggregate_agent_stats_by`
- Default value: `agent_name,template_name,username,workspace_name`

#### Collect agent stats

Collect agent stats (may increase charges for metrics storage).

- Environment variable: `CODER_PROMETHEUS_COLLECT_AGENT_STATS`
- CLI flag: [`--prometheus-collect-agent-stats`](../../reference/cli/server/index.md#--prometheus-collect-agent-stats)
- YAML key: `introspection.prometheus.collect_agent_stats`

#### Collect database metrics

Collect database query metrics (may increase charges for metrics storage). If set to false, a reduced set of database metrics are still collected.

- Environment variable: `CODER_PROMETHEUS_COLLECT_DB_METRICS`
- CLI flag: [`--prometheus-collect-db-metrics`](../../reference/cli/server/index.md#--prometheus-collect-db-metrics)
- YAML key: `introspection.prometheus.collect_db_metrics`
- Default value: `false`

#### Enable

Serve prometheus metrics on the address defined by prometheus address.

- Environment variable: `CODER_PROMETHEUS_ENABLE`
- CLI flag: [`--prometheus-enable`](../../reference/cli/server/index.md#--prometheus-enable)
- YAML key: `introspection.prometheus.enable`

### Stats collection

#### Usage stats

##### Enable

Enable the collection of application and workspace usage along with the associated API endpoints and the template insights page. Disabling this will also disable traffic and connection insights in the deployment stats shown to admins in the bottom bar of the Coder UI, and will prevent Prometheus collection of these values.

- Environment variable: `CODER_STATS_COLLECTION_USAGE_STATS_ENABLE`
- CLI flag: [`--stats-collection-usage-stats-enable`](../../reference/cli/server/index.md#--stats-collection-usage-stats-enable)
- YAML key: `introspection.statsCollection.usageStats.enable`
- Default value: `true`

### Tracing

#### Capture logs in traces

Enables capturing of logs as events in traces. This is useful for debugging, but may result in a very large amount of events being sent to the tracing backend which may incur significant costs.

- Environment variable: `CODER_TRACE_LOGS`
- CLI flag: [`--trace-logs`](../../reference/cli/server/index.md#--trace-logs)
- YAML key: `introspection.tracing.captureLogs`

#### Trace enable

Whether application tracing data is collected. It exports to a backend configured by environment variables. See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md.

- Environment variable: `CODER_TRACE_ENABLE`
- CLI flag: [`--trace`](../../reference/cli/server/index.md#--trace)
- YAML key: `introspection.tracing.enable`

#### Trace Honeycomb API key

Enables trace exporting to Honeycomb.io using the provided API Key.

- Environment variable: `CODER_TRACE_HONEYCOMB_API_KEY`
- CLI flag: [`--trace-honeycomb-api-key`](../../reference/cli/server/index.md#--trace-honeycomb-api-key)

### pprof

#### Address

The bind address to serve pprof.

- Environment variable: `CODER_PPROF_ADDRESS`
- CLI flag: [`--pprof-address`](../../reference/cli/server/index.md#--pprof-address)
- YAML key: `introspection.pprof.address`
- Default value: `127.0.0.1:6060`

#### Enable

Serve pprof metrics on the address defined by pprof address.

- Environment variable: `CODER_PPROF_ENABLE`
- CLI flag: [`--pprof-enable`](../../reference/cli/server/index.md#--pprof-enable)
- YAML key: `introspection.pprof.enable`

## MCP

### Allowed private CIDRs

MCP server destinations in private or reserved IP ranges are blocked by default for SSRF protection. This applies to OAuth2 discovery, OAuth2 token and revocation exchanges, and runtime MCP connections from coderd. This option exempts specific CIDRs.

- Environment variable: `CODER_MCP_ALLOWED_PRIVATE_CIDRS`
- CLI flag: [`--mcp-allowed-private-cidrs`](../../reference/cli/server/index.md#--mcp-allowed-private-cidrs)
- YAML key: `mcp.allowed_private_cidrs`

## Networking

### Access URL

The URL that users will use to access the Coder deployment.

- Environment variable: `CODER_ACCESS_URL`
- CLI flag: [`--access-url`](../../reference/cli/server/index.md#--access-url)
- YAML key: `networking.accessURL`

### Browser only

Whether Coder only allows connections to workspaces via the browser.

- Environment variable: `CODER_BROWSER_ONLY`
- CLI flag: [`--browser-only`](../../reference/cli/server/index.md#--browser-only)
- YAML key: `networking.browserOnly`

### Docs URL

Specifies the custom docs URL.

- Environment variable: `CODER_DOCS_URL`
- CLI flag: [`--docs-url`](../../reference/cli/server/index.md#--docs-url)
- YAML key: `networking.docsURL`
- Default value: `https://coder.com/docs`

### Proxy trusted headers

Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-Ip, True-Client-Ip, X-Forwarded-For.

- Environment variable: `CODER_PROXY_TRUSTED_HEADERS`
- CLI flag: [`--proxy-trusted-headers`](../../reference/cli/server/index.md#--proxy-trusted-headers)
- YAML key: `networking.proxyTrustedHeaders`

### Proxy trusted origins

Origin addresses to respect "proxy-trusted-headers" and X-Forwarded-Host for subdomain app routing. e.g. 192.168.1.0/24.

- Environment variable: `CODER_PROXY_TRUSTED_ORIGINS`
- CLI flag: [`--proxy-trusted-origins`](../../reference/cli/server/index.md#--proxy-trusted-origins)
- YAML key: `networking.proxyTrustedOrigins`

### Redirect to access URL

Specifies whether to redirect requests that do not match the access URL host.

- Environment variable: `CODER_REDIRECT_TO_ACCESS_URL`
- CLI flag: [`--redirect-to-access-url`](../../reference/cli/server/index.md#--redirect-to-access-url)
- YAML key: `networking.redirectToAccessURL`

### SameSite auth cookie

Controls the 'SameSite' property is set on browser session cookies.

- Environment variable: `CODER_SAMESITE_AUTH_COOKIE`
- CLI flag: [`--samesite-auth-cookie`](../../reference/cli/server/index.md#--samesite-auth-cookie)
- YAML key: `networking.sameSiteAuthCookie`
- Default value: `lax`

### Secure auth cookie

Controls if the 'Secure' property is set on browser session cookies.

- Environment variable: `CODER_SECURE_AUTH_COOKIE`
- CLI flag: [`--secure-auth-cookie`](../../reference/cli/server/index.md#--secure-auth-cookie)
- YAML key: `networking.secureAuthCookie`
- Default value: `(computed at runtime)`

### Wildcard access URL

Specifies the wildcard hostname to use for workspace applications in the form "*.example.com".

- Environment variable: `CODER_WILDCARD_ACCESS_URL`
- CLI flag: [`--wildcard-access-url`](../../reference/cli/server/index.md#--wildcard-access-url)
- YAML key: `networking.wildcardAccessURL`

### __Host prefix cookies

Recommended to be enabled. Enables `__Host-` prefix for cookies to guarantee they are only set by the right domain. This change is disruptive to any workspaces built before release 2.31, requiring a workspace restart.

- Environment variable: `CODER_HOST_PREFIX_COOKIE`
- CLI flag: [`--host-prefix-cookie`](../../reference/cli/server/index.md#--host-prefix-cookie)
- YAML key: `networking.hostPrefixCookie`
- Default value: `false`

### Cluster

Configure network clustering. Coder Servers in the primary region form a cluster by communicating directly.

#### Host

Hostname or (more commonly) IP to reach this replica for clustering.

- Environment variable: `CODER_CLUSTER_HOST`
- CLI flag: [`--cluster-host`](../../reference/cli/server/index.md#--cluster-host)
- YAML key: `networking.cluster.clusterHost`

### DERP

Most Coder deployments never have to think about DERP because all connections between workspaces and users are peer-to-peer. However, when Coder cannot establish a peer to peer connection, Coder uses a distributed relay network backed by Tailscale and WireGuard.

#### Block direct connections

Block peer-to-peer (aka. direct) workspace connections. All workspace connections from the CLI will be proxied through Coder (or custom configured DERP servers) and will never be peer-to-peer when enabled. Workspaces may still reach out to STUN servers to get their address until they are restarted after this change has been made, but new connections will still be proxied regardless.

- Environment variable: `CODER_BLOCK_DIRECT`
- CLI flag: [`--block-direct-connections`](../../reference/cli/server/index.md#--block-direct-connections)
- YAML key: `networking.derp.blockDirect`

#### Config path

Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/.

- Environment variable: `CODER_DERP_CONFIG_PATH`
- CLI flag: [`--derp-config-path`](../../reference/cli/server/index.md#--derp-config-path)
- YAML key: `networking.derp.configPath`

#### Config URL

URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/.

- Environment variable: `CODER_DERP_CONFIG_URL`
- CLI flag: [`--derp-config-url`](../../reference/cli/server/index.md#--derp-config-url)
- YAML key: `networking.derp.url`

#### Force WebSockets

Force clients and agents to always use WebSocket to connect to DERP relay servers. By default, DERP uses `Upgrade: derp`, which may cause issues with some reverse proxies. Clients may automatically fallback to WebSocket if they detect an issue with `Upgrade: derp`, but this does not work in all situations.

- Environment variable: `CODER_DERP_FORCE_WEBSOCKETS`
- CLI flag: [`--derp-force-websockets`](../../reference/cli/server/index.md#--derp-force-websockets)
- YAML key: `networking.derp.forceWebSockets`

#### Server enable

Whether to enable or disable the embedded DERP relay server.

- Environment variable: `CODER_DERP_SERVER_ENABLE`
- CLI flag: [`--derp-server-enable`](../../reference/cli/server/index.md#--derp-server-enable)
- YAML key: `networking.derp.enable`
- Default value: `true`

#### Server region name

Region name that for the embedded DERP server.

- Environment variable: `CODER_DERP_SERVER_REGION_NAME`
- CLI flag: [`--derp-server-region-name`](../../reference/cli/server/index.md#--derp-server-region-name)
- YAML key: `networking.derp.regionName`
- Default value: `Coder Embedded Relay`

#### Server relay URL

An HTTP URL that is accessible by other replicas to relay DERP traffic. Required for high availability.

- Environment variable: `CODER_DERP_SERVER_RELAY_URL`
- CLI flag: [`--derp-server-relay-url`](../../reference/cli/server/index.md#--derp-server-relay-url)
- YAML key: `networking.derp.relayURL`

#### Server STUN addresses

Addresses for STUN servers to establish P2P connections. It's recommended to have at least two STUN servers to give users the best chance of connecting P2P to workspaces. Each STUN server will get it's own DERP region, with region IDs starting at `--derp-server-region-id + 1`. Use special value 'disable' to turn off STUN completely.

- Environment variable: `CODER_DERP_SERVER_STUN_ADDRESSES`
- CLI flag: [`--derp-server-stun-addresses`](../../reference/cli/server/index.md#--derp-server-stun-addresses)
- YAML key: `networking.derp.stunAddresses`
- Default value: `stun.l.google.com:19302,stun1.l.google.com:19302,stun2.l.google.com:19302,stun3.l.google.com:19302,stun4.l.google.com:19302`

### HTTP

#### Additional CSP policy

Coder configures a Content Security Policy (CSP) to protect against XSS attacks. This setting allows you to add additional CSP directives, which can open the attack surface of the deployment. Format matches the CSP directive format, e.g. --additional-csp-policy="script-src https://example.com".

- Environment variable: `CODER_ADDITIONAL_CSP_POLICY`
- CLI flag: [`--additional-csp-policy`](../../reference/cli/server/index.md#--additional-csp-policy)
- YAML key: `networking.http.additionalCSPPolicy`

#### Disable password authentication

Disable password authentication. This is recommended for security purposes in production deployments that rely on an identity provider. Any user with the owner role will be able to sign in with their password regardless of this setting to avoid potential lock out. If you are locked out of your account, you can use the `coder server create-admin` command to create a new admin user directly in the database.

- Environment variable: `CODER_DISABLE_PASSWORD_AUTH`
- CLI flag: [`--disable-password-auth`](../../reference/cli/server/index.md#--disable-password-auth)
- YAML key: `networking.http.disablePasswordAuth`

#### Disable session expiry refresh

Disable automatic session expiry bumping due to activity. This forces all sessions to become invalid after the session expiry duration has been reached.

- Environment variable: `CODER_DISABLE_SESSION_EXPIRY_REFRESH`
- CLI flag: [`--disable-session-expiry-refresh`](../../reference/cli/server/index.md#--disable-session-expiry-refresh)
- YAML key: `networking.http.disableSessionExpiryRefresh`

#### Address

HTTP bind address of the server. Unset to disable the HTTP endpoint.

- Environment variable: `CODER_HTTP_ADDRESS`
- CLI flag: [`--http-address`](../../reference/cli/server/index.md#--http-address)
- YAML key: `networking.http.httpAddress`
- Default value: `127.0.0.1:3000`

#### Max token lifetime

The maximum lifetime duration users can specify when creating an API token.

- Environment variable: `CODER_MAX_TOKEN_LIFETIME`
- CLI flag: [`--max-token-lifetime`](../../reference/cli/server/index.md#--max-token-lifetime)
- YAML key: `networking.http.maxTokenLifetime`
- Default value: `876600h0m0s`

#### Maximum admin token lifetime

The maximum lifetime duration administrators can specify when creating an API token.

- Environment variable: `CODER_MAX_ADMIN_TOKEN_LIFETIME`
- CLI flag: [`--max-admin-token-lifetime`](../../reference/cli/server/index.md#--max-admin-token-lifetime)
- YAML key: `networking.http.maxAdminTokenLifetime`
- Default value: `168h0m0s`

#### Proxy health check interval

The interval in which coderd should be checking the status of workspace proxies.

- Environment variable: `CODER_PROXY_HEALTH_INTERVAL`
- CLI flag: [`--proxy-health-interval`](../../reference/cli/server/index.md#--proxy-health-interval)
- YAML key: `networking.http.proxyHealthInterval`
- Default value: `1m0s`

#### Session duration

The token expiry duration for browser sessions. Sessions may last longer if they are actively making requests, but this functionality can be disabled via --disable-session-expiry-refresh.

- Environment variable: `CODER_SESSION_DURATION`
- CLI flag: [`--session-duration`](../../reference/cli/server/index.md#--session-duration)
- YAML key: `networking.http.sessionDuration`
- Default value: `24h0m0s`

### TLS

Configure TLS / HTTPS for your Coder deployment. If you're running Coder behind a TLS-terminating reverse proxy or are accessing Coder over a secure link, you can safely ignore these settings.

#### Strict-Transport-Security

Controls if the 'Strict-Transport-Security' header is set on all static file responses. This header should only be set if the server is accessed via HTTPS. This value is the MaxAge in seconds of the header.

- Environment variable: `CODER_STRICT_TRANSPORT_SECURITY`
- CLI flag: [`--strict-transport-security`](../../reference/cli/server/index.md#--strict-transport-security)
- YAML key: `networking.tls.strictTransportSecurity`
- Default value: `0`

#### Strict-Transport-Security options

Two optional fields can be set in the Strict-Transport-Security header; 'includeSubDomains' and 'preload'. The 'strict-transport-security' flag must be set to a non-zero value for these options to be used.

- Environment variable: `CODER_STRICT_TRANSPORT_SECURITY_OPTIONS`
- CLI flag: [`--strict-transport-security-options`](../../reference/cli/server/index.md#--strict-transport-security-options)
- YAML key: `networking.tls.strictTransportSecurityOptions`

#### Address

HTTPS bind address of the server.

- Environment variable: `CODER_TLS_ADDRESS`
- CLI flag: [`--tls-address`](../../reference/cli/server/index.md#--tls-address)
- YAML key: `networking.tls.address`
- Default value: `127.0.0.1:3443`

#### Allow insecure ciphers

By default, only ciphers marked as 'secure' are allowed to be used. See https://github.com/golang/go/blob/master/src/crypto/tls/cipher_suites.go#L82-L95.

- Environment variable: `CODER_TLS_ALLOW_INSECURE_CIPHERS`
- CLI flag: [`--tls-allow-insecure-ciphers`](../../reference/cli/server/index.md#--tls-allow-insecure-ciphers)
- YAML key: `networking.tls.tlsAllowInsecureCiphers`
- Default value: `false`

#### Certificate files

Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.

- Environment variable: `CODER_TLS_CERT_FILE`
- CLI flag: [`--tls-cert-file`](../../reference/cli/server/index.md#--tls-cert-file)
- YAML key: `networking.tls.certFiles`

#### Ciphers

Specify specific TLS ciphers that allowed to be used. See https://github.com/golang/go/blob/master/src/crypto/tls/cipher_suites.go#L53-L75.

- Environment variable: `CODER_TLS_CIPHERS`
- CLI flag: [`--tls-ciphers`](../../reference/cli/server/index.md#--tls-ciphers)
- YAML key: `networking.tls.tlsCiphers`

#### Client auth

Policy the server will follow for TLS Client Authentication. Accepted values are "none", "request", "require-any", "verify-if-given", or "require-and-verify".

- Environment variable: `CODER_TLS_CLIENT_AUTH`
- CLI flag: [`--tls-client-auth`](../../reference/cli/server/index.md#--tls-client-auth)
- YAML key: `networking.tls.clientAuth`
- Default value: `none`

#### Client CA files

PEM-encoded Certificate Authority file used for checking the authenticity of client.

- Environment variable: `CODER_TLS_CLIENT_CA_FILE`
- CLI flag: [`--tls-client-ca-file`](../../reference/cli/server/index.md#--tls-client-ca-file)
- YAML key: `networking.tls.clientCAFile`

#### Client cert file

Path to certificate for client TLS authentication. It requires a PEM-encoded file.

- Environment variable: `CODER_TLS_CLIENT_CERT_FILE`
- CLI flag: [`--tls-client-cert-file`](../../reference/cli/server/index.md#--tls-client-cert-file)
- YAML key: `networking.tls.clientCertFile`

#### Client key file

Path to key for client TLS authentication. It requires a PEM-encoded file.

- Environment variable: `CODER_TLS_CLIENT_KEY_FILE`
- CLI flag: [`--tls-client-key-file`](../../reference/cli/server/index.md#--tls-client-key-file)
- YAML key: `networking.tls.clientKeyFile`

#### Enable

Whether TLS will be enabled.

- Environment variable: `CODER_TLS_ENABLE`
- CLI flag: [`--tls-enable`](../../reference/cli/server/index.md#--tls-enable)
- YAML key: `networking.tls.enable`

#### Key files

Paths to the private keys for each of the certificates. It requires a PEM-encoded file.

- Environment variable: `CODER_TLS_KEY_FILE`
- CLI flag: [`--tls-key-file`](../../reference/cli/server/index.md#--tls-key-file)
- YAML key: `networking.tls.keyFiles`

#### Minimum version

Minimum supported version of TLS. Accepted values are "tls10", "tls11", "tls12" or "tls13".

- Environment variable: `CODER_TLS_MIN_VERSION`
- CLI flag: [`--tls-min-version`](../../reference/cli/server/index.md#--tls-min-version)
- YAML key: `networking.tls.minVersion`
- Default value: `tls12`

## Notifications

Configure how notifications are processed and delivered.

### Dispatch timeout

How long to wait while a notification is being sent before giving up.

- Environment variable: `CODER_NOTIFICATIONS_DISPATCH_TIMEOUT`
- CLI flag: [`--notifications-dispatch-timeout`](../../reference/cli/server/index.md#--notifications-dispatch-timeout)
- YAML key: `notifications.dispatchTimeout`
- Default value: `1m0s`

### Max send attempts

The upper limit of attempts to send a notification.

- Environment variable: `CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS`
- CLI flag: [`--notifications-max-send-attempts`](../../reference/cli/server/index.md#--notifications-max-send-attempts)
- YAML key: `notifications.maxSendAttempts`
- Default value: `5`

### Method

Which delivery method to use (available options: 'smtp', 'webhook').

- Environment variable: `CODER_NOTIFICATIONS_METHOD`
- CLI flag: [`--notifications-method`](../../reference/cli/server/index.md#--notifications-method)
- YAML key: `notifications.method`
- Default value: `smtp`

### Email

Configure how email notifications are sent.

#### Force TLS

**Deprecated.** Force a TLS connection to the configured SMTP smarthost.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_FORCE_TLS`
- CLI flag: [`--notifications-email-force-tls`](../../reference/cli/server/index.md#--notifications-email-force-tls)
- YAML key: `notifications.email.forceTLS`

#### From address

**Deprecated.** The sender's address to use.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_FROM`
- CLI flag: [`--notifications-email-from`](../../reference/cli/server/index.md#--notifications-email-from)
- YAML key: `notifications.email.from`

#### Hello

**Deprecated.** The hostname identifying the SMTP server.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_HELLO`
- CLI flag: [`--notifications-email-hello`](../../reference/cli/server/index.md#--notifications-email-hello)
- YAML key: `notifications.email.hello`

#### Smarthost

**Deprecated.** The intermediary SMTP host through which emails are sent.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_SMARTHOST`
- CLI flag: [`--notifications-email-smarthost`](../../reference/cli/server/index.md#--notifications-email-smarthost)
- YAML key: `notifications.email.smarthost`

#### Email authentication

Configure SMTP authentication options.

##### Identity

**Deprecated.** Identity to use with PLAIN authentication.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_AUTH_IDENTITY`
- CLI flag: [`--notifications-email-auth-identity`](../../reference/cli/server/index.md#--notifications-email-auth-identity)
- YAML key: `notifications.email.emailAuth.identity`

##### Password

**Deprecated.** Password to use with PLAIN/LOGIN authentication.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD`
- CLI flag: [`--notifications-email-auth-password`](../../reference/cli/server/index.md#--notifications-email-auth-password)

##### Password file

**Deprecated.** File from which to load password for use with PLAIN/LOGIN authentication.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD_FILE`
- CLI flag: [`--notifications-email-auth-password-file`](../../reference/cli/server/index.md#--notifications-email-auth-password-file)
- YAML key: `notifications.email.emailAuth.passwordFile`

##### Username

**Deprecated.** Username to use with PLAIN/LOGIN authentication.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_AUTH_USERNAME`
- CLI flag: [`--notifications-email-auth-username`](../../reference/cli/server/index.md#--notifications-email-auth-username)
- YAML key: `notifications.email.emailAuth.username`

#### Email TLS

Configure TLS for your SMTP server target.

##### Certificate authority file

**Deprecated.** CA certificate file to use.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_TLS_CACERTFILE`
- CLI flag: [`--notifications-email-tls-ca-cert-file`](../../reference/cli/server/index.md#--notifications-email-tls-ca-cert-file)
- YAML key: `notifications.email.emailTLS.caCertFile`

##### Certificate file

**Deprecated.** Certificate file to use.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_TLS_CERTFILE`
- CLI flag: [`--notifications-email-tls-cert-file`](../../reference/cli/server/index.md#--notifications-email-tls-cert-file)
- YAML key: `notifications.email.emailTLS.certFile`

##### Certificate key file

**Deprecated.** Certificate key file to use.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_TLS_CERTKEYFILE`
- CLI flag: [`--notifications-email-tls-cert-key-file`](../../reference/cli/server/index.md#--notifications-email-tls-cert-key-file)
- YAML key: `notifications.email.emailTLS.certKeyFile`

##### Server name

**Deprecated.** Server name to verify against the target certificate.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_TLS_SERVERNAME`
- CLI flag: [`--notifications-email-tls-server-name`](../../reference/cli/server/index.md#--notifications-email-tls-server-name)
- YAML key: `notifications.email.emailTLS.serverName`

##### Skip certificate verification (insecure)

**Deprecated.** Skip verification of the target server's certificate (insecure).

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_TLS_SKIPVERIFY`
- CLI flag: [`--notifications-email-tls-skip-verify`](../../reference/cli/server/index.md#--notifications-email-tls-skip-verify)
- YAML key: `notifications.email.emailTLS.insecureSkipVerify`

##### StartTLS

**Deprecated.** Enable STARTTLS to upgrade insecure SMTP connections using TLS.

- Environment variable: `CODER_NOTIFICATIONS_EMAIL_TLS_STARTTLS`
- CLI flag: [`--notifications-email-tls-starttls`](../../reference/cli/server/index.md#--notifications-email-tls-starttls)
- YAML key: `notifications.email.emailTLS.startTLS`

### Inbox

#### Enabled

Enable Coder Inbox.

- Environment variable: `CODER_NOTIFICATIONS_INBOX_ENABLED`
- CLI flag: [`--notifications-inbox-enabled`](../../reference/cli/server/index.md#--notifications-inbox-enabled)
- YAML key: `notifications.inbox.enabled`
- Default value: `true`

### Webhook

#### Endpoint

The endpoint to which to send webhooks.

- Environment variable: `CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT`
- CLI flag: [`--notifications-webhook-endpoint`](../../reference/cli/server/index.md#--notifications-webhook-endpoint)
- YAML key: `notifications.webhook.endpoint`

## OAuth2

Configure OAuth2: GitHub login and user-provisioning, and Coder's own OAuth 2.1 authorization server.

### GitHub

#### Allow everyone

Allow all logins, setting this option means allowed orgs and teams must be empty.

- Environment variable: `CODER_OAUTH2_GITHUB_ALLOW_EVERYONE`
- CLI flag: [`--oauth2-github-allow-everyone`](../../reference/cli/server/index.md#--oauth2-github-allow-everyone)
- YAML key: `oauth2.github.allowEveryone`

#### Allow signups

Whether new users can sign up with GitHub.

- Environment variable: `CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS`
- CLI flag: [`--oauth2-github-allow-signups`](../../reference/cli/server/index.md#--oauth2-github-allow-signups)
- YAML key: `oauth2.github.allowSignups`

#### Allowed orgs

Organizations the user must be a member of to Login with GitHub.

- Environment variable: `CODER_OAUTH2_GITHUB_ALLOWED_ORGS`
- CLI flag: [`--oauth2-github-allowed-orgs`](../../reference/cli/server/index.md#--oauth2-github-allowed-orgs)
- YAML key: `oauth2.github.allowedOrgs`

#### Allowed teams

Teams inside organizations the user must be a member of to Login with GitHub. Structured as: `<organization-name>/<team-slug>`.

- Environment variable: `CODER_OAUTH2_GITHUB_ALLOWED_TEAMS`
- CLI flag: [`--oauth2-github-allowed-teams`](../../reference/cli/server/index.md#--oauth2-github-allowed-teams)
- YAML key: `oauth2.github.allowedTeams`

#### Client ID

Client ID for Login with GitHub.

- Environment variable: `CODER_OAUTH2_GITHUB_CLIENT_ID`
- CLI flag: [`--oauth2-github-client-id`](../../reference/cli/server/index.md#--oauth2-github-client-id)
- YAML key: `oauth2.github.clientID`

#### Client secret

Client secret for Login with GitHub.

- Environment variable: `CODER_OAUTH2_GITHUB_CLIENT_SECRET`
- CLI flag: [`--oauth2-github-client-secret`](../../reference/cli/server/index.md#--oauth2-github-client-secret)

#### Default provider enable

Enable the default GitHub OAuth2 provider managed by Coder.

- Environment variable: `CODER_OAUTH2_GITHUB_DEFAULT_PROVIDER_ENABLE`
- CLI flag: [`--oauth2-github-default-provider-enable`](../../reference/cli/server/index.md#--oauth2-github-default-provider-enable)
- YAML key: `oauth2.github.defaultProviderEnable`
- Default value: `true`

#### Device flow

Enable device flow for Login with GitHub.

- Environment variable: `CODER_OAUTH2_GITHUB_DEVICE_FLOW`
- CLI flag: [`--oauth2-github-device-flow`](../../reference/cli/server/index.md#--oauth2-github-device-flow)
- YAML key: `oauth2.github.deviceFlow`
- Default value: `false`

#### Enterprise base URL

Base URL of a GitHub Enterprise deployment to use for Login with GitHub.

- Environment variable: `CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL`
- CLI flag: [`--oauth2-github-enterprise-base-url`](../../reference/cli/server/index.md#--oauth2-github-enterprise-base-url)
- YAML key: `oauth2.github.enterpriseBaseURL`

### Provider

#### Enable

Enable the OAuth 2.1 authorization server, which lets external applications (such as MCP clients) obtain tokens for Coder on behalf of users. Disabled by default. When disabled, the OAuth2 endpoints and discovery documents return 404.

- Environment variable: `CODER_OAUTH2_PROVIDER_ENABLE`
- CLI flag: [`--oauth2-provider-enable`](../../reference/cli/server/index.md#--oauth2-provider-enable)
- YAML key: `oauth2.provider.enable`
- Default value: `false`

## OIDC

### Enable OIDC group auto create

Automatically creates missing groups from a user's groups claim.

- Environment variable: `CODER_OIDC_GROUP_AUTO_CREATE`
- CLI flag: [`--oidc-group-auto-create`](../../reference/cli/server/index.md#--oidc-group-auto-create)
- YAML key: `oidc.enableGroupAutoCreate`
- Default value: `false`

### Allow signups

Whether new users can sign up with OIDC.

- Environment variable: `CODER_OIDC_ALLOW_SIGNUPS`
- CLI flag: [`--oidc-allow-signups`](../../reference/cli/server/index.md#--oidc-allow-signups)
- YAML key: `oidc.allowSignups`
- Default value: `true`

### Allowed groups

If provided any group name not in the list will not be allowed to authenticate. This allows for restricting access to a specific set of groups. This filter is applied after the group mapping and before the regex filter.

- Environment variable: `CODER_OIDC_ALLOWED_GROUPS`
- CLI flag: [`--oidc-allowed-groups`](../../reference/cli/server/index.md#--oidc-allowed-groups)
- YAML key: `oidc.groupAllowed`

### Auth URL parameters

OIDC auth URL parameters to pass to the upstream provider.

- Environment variable: `CODER_OIDC_AUTH_URL_PARAMS`
- CLI flag: [`--oidc-auth-url-params`](../../reference/cli/server/index.md#--oidc-auth-url-params)
- YAML key: `oidc.authURLParams`
- Default value: `{"access_type": "offline"}`

### Client cert file

Pem encoded certificate file to use for oauth2 PKI/JWT authorization. The public certificate that accompanies oidc-client-key-file. A standard x509 certificate is expected.

- Environment variable: `CODER_OIDC_CLIENT_CERT_FILE`
- CLI flag: [`--oidc-client-cert-file`](../../reference/cli/server/index.md#--oidc-client-cert-file)
- YAML key: `oidc.oidcClientCertFile`

### Client ID

Client ID to use for Login with OIDC.

- Environment variable: `CODER_OIDC_CLIENT_ID`
- CLI flag: [`--oidc-client-id`](../../reference/cli/server/index.md#--oidc-client-id)
- YAML key: `oidc.clientID`

### Client key file

Pem encoded RSA private key to use for oauth2 PKI/JWT authorization. This can be used instead of oidc-client-secret if your IDP supports it.

- Environment variable: `CODER_OIDC_CLIENT_KEY_FILE`
- CLI flag: [`--oidc-client-key-file`](../../reference/cli/server/index.md#--oidc-client-key-file)
- YAML key: `oidc.oidcClientKeyFile`

### Client secret

Client secret to use for Login with OIDC.

- Environment variable: `CODER_OIDC_CLIENT_SECRET`
- CLI flag: [`--oidc-client-secret`](../../reference/cli/server/index.md#--oidc-client-secret)

### Email domain

Email domains that clients logging in with OIDC must match.

- Environment variable: `CODER_OIDC_EMAIL_DOMAIN`
- CLI flag: [`--oidc-email-domain`](../../reference/cli/server/index.md#--oidc-email-domain)
- YAML key: `oidc.emailDomain`

### Email field

OIDC claim field to use as the email.

- Environment variable: `CODER_OIDC_EMAIL_FIELD`
- CLI flag: [`--oidc-email-field`](../../reference/cli/server/index.md#--oidc-email-field)
- YAML key: `oidc.emailField`
- Default value: `email`

### Group field

This field must be set if using the group sync feature and the scope name is not 'groups'. Set to the claim to be used for groups.

- Environment variable: `CODER_OIDC_GROUP_FIELD`
- CLI flag: [`--oidc-group-field`](../../reference/cli/server/index.md#--oidc-group-field)
- YAML key: `oidc.groupField`

### Group mapping

A map of OIDC group IDs and the group in Coder it should map to. This is useful for when OIDC providers only return group IDs.

- Environment variable: `CODER_OIDC_GROUP_MAPPING`
- CLI flag: [`--oidc-group-mapping`](../../reference/cli/server/index.md#--oidc-group-mapping)
- YAML key: `oidc.groupMapping`
- Default value: `{}`

### Ignore email verified

Ignore the email_verified claim from the upstream provider.

- Environment variable: `CODER_OIDC_IGNORE_EMAIL_VERIFIED`
- CLI flag: [`--oidc-ignore-email-verified`](../../reference/cli/server/index.md#--oidc-ignore-email-verified)
- YAML key: `oidc.ignoreEmailVerified`

### Ignore UserInfo

Ignore the userinfo endpoint and only use the ID token for user information.

- Environment variable: `CODER_OIDC_IGNORE_USERINFO`
- CLI flag: [`--oidc-ignore-userinfo`](../../reference/cli/server/index.md#--oidc-ignore-userinfo)
- YAML key: `oidc.ignoreUserInfo`
- Default value: `false`

### Issuer URL

Issuer URL to use for Login with OIDC.

- Environment variable: `CODER_OIDC_ISSUER_URL`
- CLI flag: [`--oidc-issuer-url`](../../reference/cli/server/index.md#--oidc-issuer-url)
- YAML key: `oidc.issuerURL`

### Name field

OIDC claim field to use as the name.

- Environment variable: `CODER_OIDC_NAME_FIELD`
- CLI flag: [`--oidc-name-field`](../../reference/cli/server/index.md#--oidc-name-field)
- YAML key: `oidc.nameField`
- Default value: `name`

### Redirect URL

Optional override of the default redirect url which uses the deployment's access url. Useful in situations where a deployment has more than 1 domain. Using this setting can also break OIDC, so use with caution.

- Environment variable: `CODER_OIDC_REDIRECT_URL`
- CLI flag: [`--oidc-redirect-url`](../../reference/cli/server/index.md#--oidc-redirect-url)
- YAML key: `oidc.oidc-redirect-url`

### Regex group filter

If provided any group name not matching the regex is ignored. This allows for filtering out groups that are not needed. This filter is applied after the group mapping.

- Environment variable: `CODER_OIDC_GROUP_REGEX_FILTER`
- CLI flag: [`--oidc-group-regex-filter`](../../reference/cli/server/index.md#--oidc-group-regex-filter)
- YAML key: `oidc.groupRegexFilter`
- Default value: `.*`

### Scopes

Scopes to grant when authenticating with OIDC.

- Environment variable: `CODER_OIDC_SCOPES`
- CLI flag: [`--oidc-scopes`](../../reference/cli/server/index.md#--oidc-scopes)
- YAML key: `oidc.scopes`
- Default value: `openid,profile,email`

### User role default

If user role sync is enabled, these roles are always included for all authenticated users. The 'member' role is always assigned.

- Environment variable: `CODER_OIDC_USER_ROLE_DEFAULT`
- CLI flag: [`--oidc-user-role-default`](../../reference/cli/server/index.md#--oidc-user-role-default)
- YAML key: `oidc.userRoleDefault`

### User role field

This field must be set if using the user roles sync feature. Set this to the name of the claim used to store the user's role. The roles should be sent as an array of strings.

- Environment variable: `CODER_OIDC_USER_ROLE_FIELD`
- CLI flag: [`--oidc-user-role-field`](../../reference/cli/server/index.md#--oidc-user-role-field)
- YAML key: `oidc.userRoleField`

### User role mapping

A map of the OIDC passed in user roles and the groups in Coder it should map to. This is useful if the group names do not match. If mapped to the empty string, the role will ignored.

- Environment variable: `CODER_OIDC_USER_ROLE_MAPPING`
- CLI flag: [`--oidc-user-role-mapping`](../../reference/cli/server/index.md#--oidc-user-role-mapping)
- YAML key: `oidc.userRoleMapping`
- Default value: `{}`

### Username field

OIDC claim field to use as the username.

- Environment variable: `CODER_OIDC_USERNAME_FIELD`
- CLI flag: [`--oidc-username-field`](../../reference/cli/server/index.md#--oidc-username-field)
- YAML key: `oidc.usernameField`
- Default value: `preferred_username`

### OpenID Connect sign in text

The text to show on the OpenID Connect sign in button.

- Environment variable: `CODER_OIDC_SIGN_IN_TEXT`
- CLI flag: [`--oidc-sign-in-text`](../../reference/cli/server/index.md#--oidc-sign-in-text)
- YAML key: `oidc.signInText`
- Default value: `OpenID Connect`

### OpenID Connect icon URL

URL pointing to the icon to use on the OpenID Connect login button.

- Environment variable: `CODER_OIDC_ICON_URL`
- CLI flag: [`--oidc-icon-url`](../../reference/cli/server/index.md#--oidc-icon-url)
- YAML key: `oidc.iconURL`

### Signups disabled text

The custom text to show on the error page informing about disabled OIDC signups. Markdown format is supported.

- Environment variable: `CODER_OIDC_SIGNUPS_DISABLED_TEXT`
- CLI flag: [`--oidc-signups-disabled-text`](../../reference/cli/server/index.md#--oidc-signups-disabled-text)
- YAML key: `oidc.signupsDisabledText`

### Skip OIDC issuer checks (not recommended)

OIDC issuer urls must match in the request, the id_token 'iss' claim, and in the well-known configuration. This flag disables that requirement, and can lead to an insecure OIDC configuration. It is not recommended to use this flag.

- Environment variable: `CODER_DANGEROUS_OIDC_SKIP_ISSUER_CHECKS`
- CLI flag: [`--dangerous-oidc-skip-issuer-checks`](../../reference/cli/server/index.md#--dangerous-oidc-skip-issuer-checks)
- YAML key: `oidc.dangerousSkipIssuerChecks`

## Provisioning

Tune the behavior of the provisioner, which is responsible for creating, updating, and deleting workspace resources.

### Disable Terraform module cache

Disable the reuse of Terraform modules cached at template import for all templates. Modules are re-downloaded on every workspace build. Individual templates cannot opt back in.

- Environment variable: `CODER_PROVISIONER_DISABLE_MODULE_CACHE`
- CLI flag: [`--provisioner-disable-module-cache`](../../reference/cli/server/index.md#--provisioner-disable-module-cache)
- YAML key: `provisioning.disableModuleCache`
- Default value: `false`

### Force cancel interval

Time to force cancel provisioning tasks that are stuck.

- Environment variable: `CODER_PROVISIONER_FORCE_CANCEL_INTERVAL`
- CLI flag: [`--provisioner-force-cancel-interval`](../../reference/cli/server/index.md#--provisioner-force-cancel-interval)
- YAML key: `provisioning.forceCancelInterval`
- Default value: `10m0s`

### Provisioner daemon pre-shared key (PSK)

Pre-shared key to authenticate external provisioner daemons to Coder server.

- Environment variable: `CODER_PROVISIONER_DAEMON_PSK`
- CLI flag: [`--provisioner-daemon-psk`](../../reference/cli/server/index.md#--provisioner-daemon-psk)

### Provisioner daemons

Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.

- Environment variable: `CODER_PROVISIONER_DAEMONS`
- CLI flag: [`--provisioner-daemons`](../../reference/cli/server/index.md#--provisioner-daemons)
- YAML key: `provisioning.daemons`
- Default value: `3`

### Poll interval

**Deprecated** and ignored.

- Environment variable: `CODER_PROVISIONER_DAEMON_POLL_INTERVAL`
- CLI flag: [`--provisioner-daemon-poll-interval`](../../reference/cli/server/index.md#--provisioner-daemon-poll-interval)
- YAML key: `provisioning.daemonPollInterval`
- Default value: `1s`

### Poll jitter

**Deprecated** and ignored.

- Environment variable: `CODER_PROVISIONER_DAEMON_POLL_JITTER`
- CLI flag: [`--provisioner-daemon-poll-jitter`](../../reference/cli/server/index.md#--provisioner-daemon-poll-jitter)
- YAML key: `provisioning.daemonPollJitter`
- Default value: `100ms`

## Retention

Configure data retention policies for various database tables. Retention policies automatically purge old data to reduce database size and improve performance. Setting a retention duration to 0 disables automatic purging for that data type.

### API keys retention

How long expired API keys are retained before being deleted. Keeping expired keys allows the backend to return a more helpful error when a user tries to use an expired key. Set to 0 to disable automatic deletion of expired keys.

- Environment variable: `CODER_API_KEYS_RETENTION`
- CLI flag: [`--api-keys-retention`](../../reference/cli/server/index.md#--api-keys-retention)
- YAML key: `retention.api_keys`
- Default value: `7d`

### Audit logs retention

How long audit log entries are retained. Set to 0 to disable (keep indefinitely). We advise keeping audit logs for at least a year, and in accordance with your compliance requirements.

- Environment variable: `CODER_AUDIT_LOGS_RETENTION`
- CLI flag: [`--audit-logs-retention`](../../reference/cli/server/index.md#--audit-logs-retention)
- YAML key: `retention.audit_logs`
- Default value: `0`

### Boundary log retention

How long boundary audit log entries are retained. Boundary logs record HTTP requests processed by a Boundary confinement proxy. Set to 0 to disable automatic deletion (keep indefinitely). Adjust to match your organization's regulatory requirements.

- Environment variable: `CODER_BOUNDARY_LOG_RETENTION`
- CLI flag: [`--boundary-log-retention`](../../reference/cli/server/index.md#--boundary-log-retention)
- YAML key: `retention.boundary_logs`
- Default value: `0`

### Connection logs retention

How long connection log entries are retained. Set to 0 to disable (keep indefinitely).

- Environment variable: `CODER_CONNECTION_LOGS_RETENTION`
- CLI flag: [`--connection-logs-retention`](../../reference/cli/server/index.md#--connection-logs-retention)
- YAML key: `retention.connection_logs`
- Default value: `0`

### Workspace agent logs retention

How long workspace agent logs are retained. Logs from non-latest builds are deleted if the agent hasn't connected within this period. Logs from the latest build are always retained. Set to 0 to disable automatic deletion.

- Environment variable: `CODER_WORKSPACE_AGENT_LOGS_RETENTION`
- CLI flag: [`--workspace-agent-logs-retention`](../../reference/cli/server/index.md#--workspace-agent-logs-retention)
- YAML key: `retention.workspace_agent_logs`
- Default value: `7d`

## Telemetry

Telemetry is critical to our ability to improve Coder. We strip all personal information before sending data to our servers. Please only disable telemetry when required by your organization's security policy.

### Enable

Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.

- Environment variable: `CODER_TELEMETRY_ENABLE`
- CLI flag: [`--telemetry`](../../reference/cli/server/index.md#--telemetry)
- YAML key: `telemetry.enable`
- Default value: `true`

## Template Builder

### Disable Template Builder

Disable the template builder feature for guided template creation. When disabled, all /api/v2/templatebuilder/* endpoints return 404.

- Environment variable: `CODER_DISABLE_TEMPLATE_BUILDER`
- CLI flag: [`--disable-template-builder`](../../reference/cli/server/index.md#--disable-template-builder)
- YAML key: `templateBuilder.disabled`

### Registry URL

The module registry host the template builder uses for module source paths (for example, "registry.coder.com" or "mirror.internal:8443"). An http(s):// scheme and trailing slash are stripped; a path, query, fragment, or credentials is rejected.

- Environment variable: `CODER_TEMPLATE_BUILDER_REGISTRY_URL`
- CLI flag: [`--template-builder-registry-url`](../../reference/cli/server/index.md#--template-builder-registry-url)
- YAML key: `templateBuilder.registryURL`
- Default value: `registry.coder.com`

## User quiet hours schedule

Allow users to set quiet hours schedules each day for workspaces to avoid workspaces stopping during the day due to template scheduling.

### Allow custom quiet hours

Allow users to set their own quiet hours schedule for workspaces to stop in (depending on template autostop requirement settings). If false, users can't change their quiet hours schedule and the site default is always used.

- Environment variable: `CODER_ALLOW_CUSTOM_QUIET_HOURS`
- CLI flag: [`--allow-custom-quiet-hours`](../../reference/cli/server/index.md#--allow-custom-quiet-hours)
- YAML key: `userQuietHoursSchedule.allowCustomQuietHours`
- Default value: `true`

### Default quiet hours schedule

The default daily cron schedule applied to users that haven't set a custom quiet hours schedule themselves. The quiet hours schedule determines when workspaces will be force stopped due to the template's autostop requirement, and will round the max deadline up to be within the user's quiet hours window (or default). The format is the same as the standard cron format, but the day-of-month, month and day-of-week must be *. Only one hour and minute can be specified (ranges or comma separated values are not supported).

- Environment variable: `CODER_QUIET_HOURS_DEFAULT_SCHEDULE`
- CLI flag: [`--default-quiet-hours-schedule`](../../reference/cli/server/index.md#--default-quiet-hours-schedule)
- YAML key: `userQuietHoursSchedule.defaultQuietHoursSchedule`
- Default value: `CRON_TZ=UTC 0 0 * * *`

## Workspace prebuilds

Configure how workspace prebuilds behave.

### Reconciliation interval

How often to reconcile workspace prebuilds state.

- Environment variable: `CODER_WORKSPACE_PREBUILDS_RECONCILIATION_INTERVAL`
- CLI flag: [`--workspace-prebuilds-reconciliation-interval`](../../reference/cli/server/index.md#--workspace-prebuilds-reconciliation-interval)
- YAML key: `workspace_prebuilds.reconciliation_interval`
- Default value: `1m0s`

## Dangerous

> [!CAUTION]
> These options can break your deployment or weaken its security. Change them only when you understand the consequences.

### Allow path app sharing

Allow workspace apps that are not served from subdomains to be shared. Path-based app sharing is DISABLED by default for security purposes. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.

- Environment variable: `CODER_DANGEROUS_ALLOW_PATH_APP_SHARING`
- CLI flag: [`--dangerous-allow-path-app-sharing`](../../reference/cli/server/index.md#--dangerous-allow-path-app-sharing)

### Allow site owners to access path apps

Allow site-owners to access workspace apps from workspaces they do not own. Owners cannot access path-based apps they do not own by default. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.

- Environment variable: `CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS`
- CLI flag: [`--dangerous-allow-path-app-site-owner-access`](../../reference/cli/server/index.md#--dangerous-allow-path-app-site-owner-access)

---

# Telemetry

Source: https://coder.com/docs/admin/setup/telemetry

> [!NOTE]
> TL;DR: disable telemetry by setting <code>CODER_TELEMETRY_ENABLE=false</code>.

Coder collects telemetry from all installations by default. We believe our users
should have the right to know what we collect, why we collect it, and how we use
the data.

## What we collect

You can find a full list of the data we collect in our source code
[here](../../../coderd/telemetry/telemetry.go).
In particular, look at the struct types such as `Template` or `Workspace`.

As a rule, we **do not collect** the following types of information:

- Any data that could make your installation less secure
- Any data that could identify individual users, except the administrator.

For example, we do not collect parameters, environment variables, or user email
addresses. We do collect the administrator email.

Workspace agent statistics include session counts keyed by normalized application names, which can include custom IDE names that workspace agents report.

## Why we collect

Telemetry helps us understand which features are most valuable, what use cases
to focus on, and which bugs to fix first.

Most cloud-based software products collect far more data than we do. They often
offer little transparency and configurability. It's hard to imagine our favorite
SaaS products existing without their creators having a detailed understanding of
user interactions. We want to wield some of that product development power to
build self-hosted, open-source software.

## Security

In the event we discover a critical security issue with Coder, we will use
telemetry to identify affected installations and notify their administrators.

<a id="toggling"></a>

## Turn telemetry on or off

You can turn telemetry on or off using either the
`CODER_TELEMETRY_ENABLE=[true|false]` environment variable or the
`--telemetry=[true|false]` command-line flag.

---

# Configure chat lifecycle hooks

Source: https://coder.com/docs/admin/setup/chat-lifecycle-hooks

> [!NOTE]
> Chat lifecycle hooks are an experimental feature.
> The feature requires the `agent-lifecycle-hooks` experiment, and the consumer contract (including the request schema and JWT claims) may change or be removed in any release without a compatibility guarantee.

This guide is for Coder deployment administrators who need to apply an external policy service to the agent loop.
Work through it to configure the deployment, handle events in a consumer, recover from dispatch failures, and roll out enforcement.

Chat lifecycle hooks send events from the agent loop to 1 deployment-wide webhook endpoint.
The configured consumer can observe all 7 lifecycle events, add model or user context, replace mutable input, or deny selected actions.
Coder keeps no record of dispatched events or consumer decisions: any policy state, audit trail, or decision history lives in the consumer.

> [!IMPORTANT]
> A consumer can block agent activity across the deployment.
> Start with an observe-only consumer and test failure recovery before enforcing policy.

## Configure the deployment

Enable the experiment first:

```env
CODER_EXPERIMENTS=agent-lifecycle-hooks
```

Without the experiment, an enabled hook configuration is inactive: `coder server` logs a warning at startup and dispatches no hook events.
Enabled hook settings are still validated at startup when a hook URL is set. Leaving the URL unset, or setting `CODER_CHAT_HOOK_ENABLED=false`, makes the hook settings inert and skips their validation.
The experiment list is read at startup, so enabling or disabling it requires a `coder server` restart.

Set the following deployment options on `coder server`.

| Environment variable             | CLI flag                     | Default | Requirement                                                                                                                                                      |
|----------------------------------|------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `CODER_CHAT_HOOK_URL`            | `--chat-hook-url`            | Empty   | Use an `https` URL, or an `http` URL with `CODER_CHAT_HOOK_ALLOW_INSECURE`. Hooks are inactive when this value is empty.                                         |
| `CODER_CHAT_HOOK_SECRET`         | `--chat-hook-secret`         | Empty   | Required when the hook URL is set, at least 32 bytes of cryptographically random data. Coder uses this shared secret to sign HS256 JWTs.                         |
| `CODER_CHAT_HOOK_TIMEOUT`        | `--chat-hook-timeout`        | `1.5s`  | Must be greater than `0` and no more than `5s`. The timeout applies to each request.                                                                             |
| `CODER_CHAT_HOOK_ENABLED`        | `--chat-hook-enabled`        | `true`  | Set to `false` to stop dispatching without removing the URL or secret.                                                                                           |
| `CODER_CHAT_HOOK_ALLOW_INSECURE` | `--chat-hook-allow-insecure` | `false` | Set to `true` to allow a plain `http` hook URL. Plain HTTP lets an attacker on the network forge hook responses, so only enable it on a network you fully trust. |

Treat `CODER_CHAT_HOOK_ENABLED=false` as the break-glass control.
Changing deployment options requires the normal `coder server` configuration rollout for your installation.

Use a dedicated secret and rotate it through your existing secret-management process.
Rotation is a hard cutover: Coder signs with exactly one secret, so dispatches fail until the consumer accepts the new value.
Rotate during a maintenance window, or temporarily set `CODER_CHAT_HOOK_ENABLED=false` for the cutover if blocked chats are worse than unreviewed ones for your deployment.
Coder requires the configured URL to use HTTPS unless `CODER_CHAT_HOOK_ALLOW_INSECURE` is set.
Plain HTTP removes more than transport privacy: hook responses are what allow or deny tool calls and can rewrite prompts and tool inputs, so anyone on the network path can forge them. Coder logs a warning at startup when hooks run over plain HTTP.
A TLS terminator can forward the request to a consumer over plain HTTP on a trusted local network.
Configure the consumer with the same `CODER_CHAT_HOOK_URL` value, because that URL is the audience Coder signs into every dispatch.
The consumer compares the `aud` claim against its configured audience and rejects a mismatch.
It derives nothing from the request URL, the `Host` header, or forwarding headers, so the number of proxy hops in front of it doesn't affect the check.

## Handle lifecycle events

Coder sends an HTTP `POST` request for each event.
The JSON body contains `type`, `meta`, and event-specific `data`.
The `meta` object includes `dispatch_id`, `schema_version`, `chat_id`, `owner_id`, and optional workspace and turn IDs.
Events from subagent chats also carry `parent_chat_id` and `root_chat_id` so a consumer can correlate a subagent subtree with the user-facing conversation and apply the parent's policy context.
The current `schema_version` is `1`.

Handle the events your policy needs, using the data Coder sends with each one:

| Event                | When Coder sends it                                                 | Decision-relevant data                                                 |
|----------------------|---------------------------------------------------------------------|------------------------------------------------------------------------|
| `session_start`      | A chat session starts, resumes, or clears                           | `source` (`startup`, `resume`, or `clear`)                             |
| `user_prompt_submit` | A user submits a prompt, or `spawn_agent` submits a subagent prompt | `prompt` and `parts`                                                   |
| `pre_tool_use`       | Before a non-provider-executed tool runs                            | `tool_use_id`, `tool_name`, and `tool_input`                           |
| `post_tool_use`      | After a non-provider-executed tool returns                          | `tool_use_id`, `tool_name`, and either `tool_response` or `tool_error` |
| `pre_compact`        | Before Coder compacts chat context                                  | No event-specific fields                                               |
| `post_compact`       | After Coder compacts chat context                                   | No event-specific fields                                               |
| `stop`               | The model stops a turn                                              | No event-specific fields                                               |

Provider-executed tools don't produce `pre_tool_use` or `post_tool_use` events because the provider executes them outside Coder's tool runtime.

For `pre_tool_use`, `tool_input` carries the model's JSON bytes with key spelling and order preserved, so a policy can read them exactly as the model wrote them.
Coder's built-in tools decode that JSON with Go, which matches property names case-insensitively and keeps the last match, so `{"path":"/allowed","PATH":"/secret"}` could make a policy approve `/allowed` while the tool opens `/secret`.
Coder rejects a built-in tool call whose input repeats a key or spells a schema property with different capitalization, before dispatching `pre_tool_use`.
This check doesn't cover dynamic and MCP tools, because the client and the workspace agent execute those calls rather than `coderd`.
A policy that gates them must validate their input itself.
The chat `edit_files` tool reads `old_text` and `new_text` and, for rollout compatibility, also accepts the deprecated `search` and `replace` keys when the new fields are empty. A policy that gates edit content should inspect `old_text` and `new_text`, and `search`/`replace` while the compatibility window lasts.

For `user_prompt_submit`, `prompt` concatenates the original submitted text parts, and `parts` carries the original structured message, including non-text parts such as file references.
These values are captured before the consumer's override or injected context changes the stored prompt.
A consumer that gates prompt content must inspect `parts`.

### Verify each request

Coder sends the JWT in the `Authorization: Bearer <token>` header.
A consumer must apply all of the following checks before it uses the body:

- Accept only the `HS256` algorithm and verify the signature with `CODER_CHAT_HOOK_SECRET`.
- Check that `iss` is the Coder deployment ID associated with the secret.
- Check that `aud` exactly matches `CODER_CHAT_HOOK_URL`.
- Check `nbf` and reject expired tokens using `exp`.
- Check that `jti` equals the request `meta.dispatch_id`.
- Check that the JWT event `type` equals the body event `type`.
- Compute SHA-256 over the exact request body bytes and compare it with `body_sha256`.
- Check that `sub` has the form `coder:chat:<chat ID>` and that its chat ID matches `meta.chat_id`.

The Go consumer SDK in `codersdk/x/agenthooks` implements the wire types, JWT verification, body binding, audience checks, and event routing.
Use `agenthooks.NewHTTPHandler` to build an `http.Handler` from callbacks for the events your consumer handles.
Pass the deployment's `CODER_CHAT_HOOK_URL` as the expected audience, because a handler built without one rejects every request.
Pass `agenthooks.WithExpectedIssuer` with the deployment ID associated with the secret to enforce the `iss` check.
Without it, `NewHTTPHandler` accepts any non-empty `iss` signed with the shared secret, so use a secret dedicated to one deployment or always set the expected issuer.

### Return a response

Return any `2xx` status with an empty body for a no-op response.
An empty JSON object has the same effect.
If the response has a body, return a JSON object with these optional fields.
Coder rejects a response body with unknown fields, duplicate JSON keys, or trailing data as malformed, so the dispatch fails closed instead of misreading the decision.

| Field           | Effect                                                                                                                                                                         |
|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `permission`    | Allows or denies mutable input for `user_prompt_submit` and `pre_tool_use` only.                                                                                               |
| `model_context` | Adds text visible to the model. The value is limited to 16&nbsp;KiB. The text is absent from the user-visible transcript, but users may infer its effects from model behavior. |
| `user_message`  | Adds a message visible to the user.                                                                                                                                            |

The `permission.decision` value supports `allow` and `deny`.
Any other value causes the dispatch to fail closed.

Permission rules depend on the event:

- For `user_prompt_submit`, `allow` requires `input_override` in the exact form `{"prompt":"replacement text"}`.
  Coder stores and sends the replacement prompt instead of the original prompt.
  The override replaces only submitted text, matching the concatenated `prompt` field the consumer receives.
  Attachments and file references remain in `parts`, so consumers that must block them should inspect `parts` and return `deny`.
- For `pre_tool_use`, `allow` requires `input_override` containing the replacement tool input.
  Coder persists the replacement with the tool call and executes the tool with it.
  An override for a built-in tool must not repeat a key or vary the capitalization of a schema property; an ambiguous override fails the dispatch closed because the model can't correct it.
  The stored call is marked as rewritten, and the chat shows a "Modified by policy" badge.
  The marker is client-facing, so return `model_context` if the model also needs an explanation of the rewrite.
- For either event, `deny` blocks the input and must not include `input_override`.
  A denied prompt isn't persisted: Coder rejects the submission and surfaces any returned `user_message` in the rejection, ignoring `model_context`.
  A denied tool call becomes a synthetic error result, and any returned `model_context` reaches the model separately, so the model can choose another action.
- For all other events, omit `permission`.

For `user_prompt_submit`, `model_context` and `user_message` are stored as typed parts of the prompt message itself: the model-context part goes to the model but never to clients, and the user-message part is shown to the user attached to the prompt but never sent to the model.
For a denied `pre_tool_use`, the synthetic denied tool result stays visible to both audiences, while `model_context` becomes a model-only transcript message so it never reaches clients.
Other hook effects become ordinary transcript messages with audience-specific visibility, except that a `pre_compact` `model_context` guides the compaction summary instead of entering the transcript.
Coder dispatches `user_prompt_submit` exactly once per submission, when the prompt is admitted (sent, queued, edited, or used to create a chat or subagent), and applies the response effects to the final stored prompt content.

### When tool calls are admitted

Coder dispatches `pre_tool_use` once per tool call, after the model finishes proposing it and before the assistant message is stored. The stored message therefore carries the input the tool actually runs with, and stored message content is never rewritten afterwards.

Two consequences follow:

- Clients stream the model's proposed tool input while the dispatch is in flight, then converge on the stored input once the message is committed.
  A rewritten call keeps displaying the original input until the whole batch is admitted, and the row spinner remains after the live **Thinking** indicator clears.
  Coder dispatches a batch sequentially, so that window is bounded by `CODER_CHAT_HOOK_TIMEOUT` multiplied by the number of tool calls in the step, not by a single timeout.
- A tool call that is already in chat history was admitted before it was stored, so Coder executes it with the stored input instead of dispatching a second decision. If a consumer's policy changes between those two points, the change applies to later calls, not to calls already admitted. A call stored before hooks were configured is likewise not admitted retroactively, the same way an earlier prompt isn't.

The per-chat debug endpoint records what the model proposed, including tool input that a consumer replaced. It reports provider behavior and is not part of the chat transcript.

## Plan failure recovery

Lifecycle hooks are fail closed.
Coder treats a timeout, connection failure, non-`2xx` response, malformed response, or unsupported response field combination as a hook dispatch failure.
A failure during generation moves the chat to the error state and records the dispatch ID in its error details.
A failed prompt dispatch for an existing idle chat can also move that chat to the error state even though the API request is rejected.
If the first `user_prompt_submit` dispatch fails during chat creation, Coder rejects the request and doesn't create the chat.
If `post_tool_use` fails for a client-submitted tool result, Coder rejects the submission without committing the results, and the client can resubmit them after the consumer recovers.
If a hook dispatch fails after Coder has already executed one or more tools in a batch, Coder commits the tool results first so the transcript reflects the completed side effects, then moves the chat to the error state.
This covers a failed `post_tool_use` for an executed tool and a failed `user_prompt_submit` for a subagent spawn, where the spawn is refused but the tools that ran alongside it keep their results.

Dispatch precedes persistence, so a delivered event doesn't guarantee that the operation commits.
Coder checks admission before dispatching, but concurrent requests can still fail admission afterward, for example two sends racing for the last queue slot or duplicate submissions of the same tool results.
The consumer then observes an event for a request that Coder rejects, and the rejected request doesn't persist a prompt or tool result.
Treat events as attempt notifications rather than proof of a committed operation, and key idempotent tool-event processing on `tool_use_id`.

Each `coderd` replica runs at most 256 dispatches at once and waits up to 250&nbsp;ms for a free slot; a dispatch that waits out that limit fails as over capacity.
The limit is per replica rather than deployment-wide, so size the consumer for 256 concurrent requests per replica.
Slow consumer responses hold slots for longer, so a slow consumer turns a burst of chat activity into over-capacity failures.
Prompt admission (creating, sending, or editing a message) can hold at most 192 of a replica's slots, so at least 64 stay reachable only by dispatches for work a chat already admitted.
That bound stops a burst of new submissions from consuming every slot, but it doesn't make the remaining slots sufficient: a saturated dispatcher can still fail a dispatch for a running chat and leave that chat in the error state.
Watch `coderd_chatd_hook_dispatches_total{result="over_capacity"}` to see whether the consumer's latency is turning normal traffic into rejections.

Delivery is best-effort and can duplicate.
Coder never queues a failed dispatch for redelivery, so plan for duplicates without assuming every event arrives.
Coder retries one connection failure per dispatch with the same JWT, so use `dispatch_id` to recognize a repeated HTTP attempt and return the same response.
Coder also re-dispatches the same logical event with a new `dispatch_id` whenever an operation runs again, for example when a chat recovers after a crash and retries a pending tool call, or when a user retries a turn that failed before committing.
Every tool call that reaches execution is validated through a fresh `pre_tool_use` dispatch; Coder never reuses an earlier decision on the consumer's behalf.
Calls that Coder rejects before execution, such as input that isn't valid JSON, ambiguous input, or a batch that mixes an exclusive tool with other calls, produce an error result for the model without a dispatch.

Use event-specific identifiers for logical duplicates:

| Events                                | Deduplication guidance                                                                                                                     |
|---------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| `pre_tool_use`, `post_tool_use`       | Key by `chat_id`, event type, and `tool_use_id`.                                                                                           |
| `session_start`                       | Response effects can repeat after runner or process replacement. Make them safe to apply more than once.                                   |
| `user_prompt_submit`                  | Dispatch occurs before a message ID exists. Avoid non-idempotent external effects because identical prompt content can be submitted twice. |
| `pre_compact`, `post_compact`, `stop` | Don't rely on `turn_id` surviving recovery. Make external effects safe to repeat.                                                          |

Rejecting duplicates breaks Coder's retries. Return the same decision whenever the payload identifies the same logical event.

After the consumer is healthy, send another message to an existing errored chat to resume it.
Coder emits `session_start` when the agent loop starts again, with `source` set to `resume` when the chat already contains an assistant reply and `startup` otherwise.
If the consumer continues blocking chat activity, set `CODER_CHAT_HOOK_ENABLED=false` and roll out the Coder deployment configuration before users retry.

## Roll out enforcement in stages

Use the following rollout sequence:

1. Deploy a consumer that verifies every request, logs the event and identifiers, and always returns a `2xx` status with an empty response.
2. Configure the hook URL, secret, and timeout on a test deployment.
3. Exercise normal chats, tool calls, compaction, consumer timeouts, and consumer restarts.
4. Review the consumer's own logs for event coverage and unexpected failures.
5. Add policy responses for a narrow event or tool set.
6. Expand enforcement after the consumer logs show the expected decisions and failure rate.

Keep the break-glass procedure available throughout the rollout.

## Start from the reference consumer

The reference consumer at `scripts/agenthooks-server` uses `agenthooks.NewHTTPHandler` and logs 1 JSON object for each event.
Log-only mode returns an empty response for every verified event.
With log-only mode disabled, the optional example flags can deny tool names by regular expression or replace matching prompt text before the agent loop uses it.
It also demonstrates consumer-owned state: it remembers `pre_tool_use` decisions in memory keyed by chat and tool-use ID, replays them for duplicate deliveries, and marks the duplicates in its log output.

Run the consumer from a Coder source checkout:

```sh
CODER_AGENTHOOKS_SECRET='<shared-secret>' \
  go run ./scripts/agenthooks-server \
  --listen 127.0.0.1:8081 \
  --audience 'https://hooks.example.com' \
  --log-only=true
```

The server confirms the listener and then stays in the foreground, printing 1 JSON object per event it receives:

```output
Agent hooks server listening on 127.0.0.1:8081 in log-only mode
```

The reference server accepts optional TLS certificate and key paths.
For local testing with plain HTTP, either set `CODER_CHAT_HOOK_ALLOW_INSECURE=true` and use the `http` URL directly, or place an HTTPS reverse proxy in front of the consumer and pass the proxy's URL as `--audience`.
Run `go run ./scripts/agenthooks-server --help` for all flags and environment variable names.

## Audit dispatches

Coder doesn't store dispatched events or consumer decisions.
The consumer's own logs are the audit trail: log the `dispatch_id`, the stable identifiers, and the returned decision for every event.
Use the `dispatch_id` recorded in a chat's error details to correlate a failed dispatch with the consumer's logs.
Consumer logs can contain prompts, tool input, response context, and user messages, so apply the same access controls that you use for other sensitive chat data.

---

# Data Retention

Source: https://coder.com/docs/admin/setup/data-retention

Coder supports configurable retention policies that automatically purge old
Audit Logs, Connection Logs, Workspace Agent Logs, API keys, and AI Gateway
records. These policies help manage database growth by removing records older
than a specified duration.

## Overview

Large deployments can accumulate significant amounts of data over time.
Retention policies help you:

- **Reduce database size**: Automatically remove old records to free disk space.
- **Improve performance**: Smaller tables mean faster queries and backups.
- **Meet compliance requirements**: Configure retention periods that align with
  your organization's data retention policies.

> [!NOTE]
> Retention policies are disabled by default (set to `0`) to preserve existing behavior.
> The exceptions are API keys and workspace agent logs, which default to 7&nbsp;days.

## Configuration

You can configure retention policies using CLI flags, environment variables, or
a YAML configuration file.

### Settings

| Setting              | CLI Flag                           | Environment Variable                   | Default        | Description                             |
|----------------------|------------------------------------|----------------------------------------|----------------|-----------------------------------------|
| Audit Logs           | `--audit-logs-retention`           | `CODER_AUDIT_LOGS_RETENTION`           | `0` (disabled) | How long to retain Audit Log entries    |
| Connection Logs      | `--connection-logs-retention`      | `CODER_CONNECTION_LOGS_RETENTION`      | `0` (disabled) | How long to retain Connection Logs      |
| API Keys             | `--api-keys-retention`             | `CODER_API_KEYS_RETENTION`             | `7d`           | How long to retain expired API keys     |
| Workspace Agent Logs | `--workspace-agent-logs-retention` | `CODER_WORKSPACE_AGENT_LOGS_RETENTION` | `7d`           | How long to retain workspace agent logs |
| AI Gateway           | `--ai-gateway-retention`           | `CODER_AI_GATEWAY_RETENTION`           | `60d`          | How long to retain AI Gateway records   |

> [!NOTE]
> AI Gateway retention is configured separately from other retention settings.
> See [AI Gateway Setup](../../ai-coder/ai-gateway/setup.md#data-retention) for
> detailed configuration options.

### Duration Format

Retention durations support days (`d`) and weeks (`w`) in addition to standard
Go duration units (`h`, `m`, `s`):

- `7d` - 7&nbsp;days
- `2w` - 2&nbsp;weeks
- `30d` - 30&nbsp;days
- `90d` - 90&nbsp;days
- `365d` - 1&nbsp;year

### CLI Example

```sh
coder server \
  --audit-logs-retention=365d \
  --connection-logs-retention=90d \
  --api-keys-retention=7d \
  --workspace-agent-logs-retention=7d \
  --ai-gateway-retention=60d
```

### Environment Variables Example

```sh
export CODER_AUDIT_LOGS_RETENTION=365d
export CODER_CONNECTION_LOGS_RETENTION=90d
export CODER_API_KEYS_RETENTION=7d
export CODER_WORKSPACE_AGENT_LOGS_RETENTION=7d
export CODER_AI_GATEWAY_RETENTION=60d
```

### YAML Configuration Example

```yaml
retention:
  audit_logs: 365d
  connection_logs: 90d
  api_keys: 7d
  workspace_agent_logs: 7d

ai_gateway:
  retention: 60d
```

## How Retention Works

### Background Purge Process

Coder runs a background process that periodically deletes old records. The
purge process:

1. Runs approximately every 10&nbsp;minutes.
2. Processes records in batches to avoid database lock contention.
3. Deletes records older than the configured retention period.
4. Logs the number of deleted records for monitoring.

### Effective Retention

Each retention setting controls its data type independently:

- When set to a non-zero duration, records older than that duration are deleted.
- When set to `0`, retention is disabled and data is kept indefinitely.

### API Keys Special Behavior

API key retention only affects **expired** keys. A key is deleted only when:

1. The key has expired (past its `expires_at` timestamp).
2. The key has been expired for longer than the retention period.

Setting `--api-keys-retention=7d` deletes keys that expired more than 7&nbsp;days ago.
Active keys are never deleted by the retention policy.

Keeping expired keys for a short period allows Coder to return a more helpful
error message when users attempt to use an expired key.

### Workspace Agent Logs Behavior

Workspace agent logs are deleted based on when the agent last connected, not the
age of the logs themselves. **Logs from the latest build of each workspace are
always retained** regardless of when the agent last connected. This ensures you
can always debug issues with active workspaces.

For non-latest builds, logs are deleted if the agent hasn't connected within the retention period.
Setting `--workspace-agent-logs-retention=7d` deletes logs for agents that haven't connected in 7&nbsp;days (excluding those from the latest build).

### AI Gateway Data Behavior

AI Gateway retention applies to interception records and all related data, including token usage, prompts, and tool invocations.
The default of 60&nbsp;days provides a reasonable balance between storage costs and the ability to analyze usage patterns.

For details on what data is retained, see the
[AI Gateway Data Retention](../../ai-coder/ai-gateway/setup.md#data-retention)
documentation.

## Best Practices

### Recommended Starting Configuration

For most deployments, we recommend:

```yaml
retention:
  audit_logs: 365d
  connection_logs: 90d
  api_keys: 7d
  workspace_agent_logs: 7d

ai_gateway:
  retention: 60d
```

### Compliance Considerations

> [!WARNING]
> Audit Logs provide critical security and compliance information. Purging
> Audit Logs may impact your organization's ability to investigate security
> incidents or meet compliance requirements. Consult your security and
> compliance teams before configuring Audit Log retention.

Common compliance frameworks have varying retention requirements:

- **SOC 2**: Typically requires 1&nbsp;year of audit logs.
- **HIPAA**: Requires 6&nbsp;years for certain records.
- **PCI DSS**: Requires 1&nbsp;year of audit logs, with 3&nbsp;months immediately available.
- **GDPR**: Requires data minimization but does not specify maximum retention.

### External Log Aggregation

If you use an external log aggregation system (Splunk, Datadog, etc.), you can
configure shorter retention periods in Coder since logs are preserved
externally. See
[Capture and export audit logs](../security/audit-logs.md#capture-and-export-audit-logs)
for details on exporting logs.

### Database Maintenance

After enabling retention policies, you may want to run a `VACUUM` operation on
your PostgreSQL database to reclaim disk space. See
[Maintenance Procedures](../security/audit-logs.md#maintenance-procedures-for-the-audit-logs-table)
for guidance.

<a id="keeping-data-indefinitely"></a>

## Keep data indefinitely

To keep data indefinitely for any data type, set its retention value to `0`:

```yaml
retention:
  audit_logs: 0s           # Keep audit logs forever
  connection_logs: 0s      # Keep connection logs forever
  api_keys: 0s             # Keep expired API keys forever
  workspace_agent_logs: 0s # Keep workspace agent logs forever

ai_gateway:
  retention: 0s            # Keep AI Gateway records forever
```

## Monitoring

The purge process logs deletion counts at the `DEBUG` level. To monitor
retention activity, enable debug logging or search your logs for entries
containing the table name (e.g., `audit_logs`, `connection_logs`, `api_keys`).

## Related Documentation

- [Audit Logs](../security/audit-logs.md): Learn about Audit Logs and manual
  purge procedures.
- [Connection Logs](../monitoring/connection-logs.md): Learn about Connection
  Logs and monitoring.
- [AI Gateway](../../ai-coder/ai-gateway/index.md): Learn about AI Gateway for
  centralized LLM and MCP proxy management.
- [AI Gateway Setup](../../ai-coder/ai-gateway/setup.md#data-retention): Configure
  AI Gateway data retention.
- [AI Gateway Monitoring](../../ai-coder/ai-gateway/monitoring.md): Monitor AI
  Gateway usage and metrics.

---

# Users

Source: https://coder.com/docs/admin/users

By default, Coder is accessible via password authentication. For production
deployments, we recommend using an SSO authentication provider with multi-factor
authentication (MFA). It is your responsibility to ensure the auth provider
enforces MFA correctly.

<a id="configuring-sso"></a>

## Configure SSO

- [OpenID Connect](./oidc-auth/index.md) (e.g. Okta, KeyCloak, PingFederate, Azure AD)
- [GitHub](./github-auth.md) (or GitHub Enterprise)

## Groups

Multiple users can be organized into logical groups to control which templates
they can use. While groups can be manually created in Coder, we recommend
syncing them from your identity provider.

- [Learn more about Groups](./groups-roles.md)
- [Group & Role Sync](./idp-sync.md)

## Roles

Roles determine which actions users can take within the platform. Typically,
most developers in your organization have the `Member` role, allowing them to
create workspaces. Other roles have administrative capabilities such as
auditing, managing users, and managing templates.

- [Learn more about Roles](./groups-roles.md)
- [Group & Role Sync](./idp-sync.md)

## User status

Coder user accounts can have different status types: active, dormant, and
suspended.

### Active user

An _active_ user account in Coder is the default and desired state for all
users. When a user's account is marked as _active_, they have complete access to
the Coder platform and can utilize all of its features and functionalities
without any limitations. Active users can access workspaces, templates, and
interact with Coder using CLI.

### Dormant user

A user account is set to _dormant_ status when they have not yet logged in, or have not logged into the Coder platform for the past 90&nbsp;days.
Once the user logs in to the platform, the account status will switch to _active_.

Dormant accounts do not count towards the total number of licensed seats in a
Coder subscription, allowing organizations to optimize their license usage.

### Suspended user

When a user's account is marked as _suspended_ in Coder, it means that the
account has been temporarily deactivated, and the user is unable to access the
platform.

Only user administrators or owners have the necessary permissions to manage
suspended accounts and decide whether to lift the suspension and allow the user
back into the Coder environment. This level of control ensures that
administrators can enforce security measures and handle any compliance-related
issues promptly.

Similar to dormant users, suspended users do not count towards the total number
of licensed seats.

## Create a user

To create a user with the web UI:

1. Log in as a user admin.
2. Go to **Users** > **New user**.
3. Enter the **Username**, **Email**, and **Password**.
4. Select **Save**.

The new user appears in the **Users** list.
You can assign roles on this page before you save, or later from the user's actions menu.

To create a user via the Coder CLI, run:

```sh
coder users create
```

When prompted, provide the **username** and **email** for the new user.

You'll receive a response that includes the following; share the instructions
with the user so that they can log into Coder:

```console
Download the Coder command line for your operating system:
https://github.com/coder/coder/releases/latest

Run  coder login https://<accessURL>.coder.app  to authenticate.

Your email is:  email@exampleCo.com
Your password is:  <redacted>

Create a workspace   coder create !
```

## Suspend a user

User admins can suspend a user, removing the user's access to Coder.

To suspend a user via the web UI:

1. Go to **Users**.
2. Find the user you want to suspend, select the vertical ellipsis to the right,
   and select **Suspend**.
3. In the confirmation dialog, select **Suspend**.

To suspend a user via the CLI, run:

```sh
coder users suspend <username|user_id>
```

Confirm the user suspension by typing **yes** and pressing **enter**.

## Activate a suspended user

User admins can activate a suspended user, restoring their access to Coder.

To activate a user via the web UI:

1. Go to **Users**.
2. Find the user you want to activate, select the vertical ellipsis to the right,
   and select **Activate**.
3. In the confirmation dialog, select **Activate**.

To activate a user via the CLI, run:

```sh
coder users activate <username|user_id>
```

Confirm the user activation by typing **yes** and pressing **enter**.

## Reset a password

As of 2.17.0, users can reset their password independently on the login screen
by selecting "Forgot Password." This feature requires
[email notifications](../monitoring/notifications/index.md#smtp-email) to be
configured on the deployment.

To reset a user's password as an administrator via the web UI:

1. Go to **Users**.
2. Find the user whose password you want to reset, select the vertical ellipsis
   to the right, and select **Reset password**.
3. Coder displays a temporary password that you can send to the user; copy the
   password and select **Reset password**.

Coder will prompt the user to change their temporary password immediately after
logging in.

You can also reset a password via the CLI:

```sh
# run `coder reset-password <username> --help` for usage instructions
coder reset-password <username>
```

> [!NOTE]
> Resetting a user's password, e.g., the initial `owner` role-based user, only
> works when run on the host running the Coder control plane.

<a id="resetting-a-password-on-kubernetes"></a>

### Reset a password on Kubernetes

```sh
kubectl exec -it deployment/coder -n coder -- /bin/bash

coder reset-password <username>
```

## User filtering

In the Coder UI, you can filter your users using pre-defined filters or by
utilizing the Coder's filter query. The examples provided below demonstrate how
to use the Coder's filter query:

- To find active users, use the filter `status:active`.
- To find admin users, use the filter `role:admin`.
- To find users who have not been active since July 2023:
  `status:active last_seen_before:"2023-07-01T00:00:00Z"`
- To find users who were created between January 1 and January 18, 2023:
  `created_before:"2023-01-18T00:00:00Z" created_after:"2023-01-01T23:59:59Z"`
- To find users who login using Github:
  `login_type:github`
- To find service accounts: `service_account:true`.

Any text that is not part of a `key:value` filter is treated as a free-text
search and matches against a user's username, email, and display name. For
example, entering `jane` returns users whose username, email, or display name
contains `jane`.

The following filters are supported:

- `username` - Matches the exact username of the user. The match ignores
  letter case.
- `email` - Matches the exact email address of the user. The match ignores
  letter case.
- `name` - Matches part of the display name of the user. The match ignores
  letter case.
- `status` - Indicates the status of the user. It can be either `active`,
  `dormant` or `suspended`.
- `role` - Represents the role of the user. You can refer to the
  [TemplateRole documentation](https://pkg.go.dev/github.com/coder/coder/v2/codersdk#TemplateRole)
  for a list of supported user roles.
- `last_seen_before` and `last_seen_after` - The last time a user has used the
  platform (e.g. logging in, any API requests, connecting to workspaces). Uses
  the RFC3339Nano format.
- `created_before` and `created_after` - The time a user was created. Uses the
  RFC3339Nano format.
- `login_type` - Represents the login type of the user. Refer to the [LoginType documentation](https://pkg.go.dev/github.com/coder/coder/v2/codersdk#LoginType) for a list of supported values
- `service_account` - Can be either `true` to only include service accounts or
  `false` to filter them out. If omitted, both service and regular accounts and
  are returned.

## Edit a user's profile

To edit a user's display name or username with the web UI:

1. Log in as a user admin.
2. Go to **Users**.
3. Open the actions menu for the user and select **Edit**.
4. Make any desired changes.
5. Select **Save**.

## Retrieve your list of Coder users

<div class="tabs">

You can use the Coder CLI or API to retrieve your list of users.

### CLI

Use `users list` with `jq` to export the list of users to a CSV file:

```sh
coder users list --output json | \
  jq -r '["username","email","created_at","status"], (.[] | [.username, .email, .created_at, .status]) | @csv' > users.csv
```

Visit the [users list](../../reference/cli/users/list.md) documentation for more options.

### API

Use [get users](../../reference/api/users.md#get-users):

```sh
curl -X GET http://coder-server:8080/api/v2/users \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

To export the results to a CSV file, you can use [`jq`](https://jqlang.org/) to process the JSON response:

```sh
curl -X GET http://coder-server:8080/api/v2/users \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY' | \
  jq -r '.users | (map(keys) | add | unique) as $cols | $cols, (.[] | [.[$cols[]]] | @csv)' > users.csv
```

Visit the [get users](../../reference/api/users.md#get-users) documentation for more options.

</div>

---

# OpenID Connect

Source: https://coder.com/docs/admin/users/oidc-auth

The following steps through how to integrate any OpenID Connect provider (Okta,
Active Directory, etc.) to Coder.

## Step 1: Set Redirect URI with your OIDC provider

Your OIDC provider will ask you for the following parameter:

- **Redirect URI**: Set to `https://coder.domain.com/api/v2/users/oidc/callback`

## Step 2: Configure Coder with the OpenID Connect credentials

Set the following environment variables on your Coder deployment and restart Coder:

```dotenv
CODER_OIDC_ISSUER_URL="https://issuer.corp.com"
CODER_OIDC_EMAIL_DOMAIN="your-domain-1,your-domain-2"
CODER_OIDC_CLIENT_ID="533...des"
CODER_OIDC_CLIENT_SECRET="G0CSP...7qSM"
```

## OIDC Claims

When a user logs in for the first time via OIDC, Coder will merge both the
claims from the ID token and the claims obtained from hitting the upstream
provider's `userinfo` endpoint, and use the resulting data as a basis for
creating a new user or looking up an existing user.

To troubleshoot claims, set `CODER_LOG_FILTER=".*got oidc claims.*"` and follow the logs while
signing in via OIDC as a new user. Coder will log the claim fields returned by
the upstream identity provider in a message containing the string
`got oidc claims`, as well as the user info returned.

> [!NOTE]
> If you need to ensure that Coder only uses information from the ID
> token and does not hit the UserInfo endpoint, you can set the configuration
> option `CODER_OIDC_IGNORE_USERINFO=true`.

### Email Addresses

By default, Coder will look for the OIDC claim named `email` and use that value
for the newly created user's email address.

If your upstream identity provider users a different claim, you can set
`CODER_OIDC_EMAIL_FIELD` to the desired claim.

> [!NOTE]
> If this field is not present, Coder will attempt to use the claim
> field configured for `username` as an email address. If this field is not a
> valid email address, OIDC logins will fail.

### Email Address Verification

Coder requires all OIDC email addresses to be verified by default. If the
`email_verified` claim is present in the token response from the identity
provider, Coder will validate that its value is `true`. If needed, you can
disable this behavior with the following setting:

```dotenv
CODER_OIDC_IGNORE_EMAIL_VERIFIED=true
```

> [!NOTE]
> This will cause Coder to implicitly treat all OIDC emails as
> "verified", regardless of what the upstream identity provider says.

### Usernames

When a new user logs in via OIDC, Coder will by default use the value of the
claim field named `preferred_username` as the username.

If your upstream identity provider uses a different claim, you can set
`CODER_OIDC_USERNAME_FIELD` to the desired claim.

> [!NOTE]
> If this claim is empty, the email address will be stripped of the
> domain, and become the username (e.g. `example@coder.com` becomes `example`).
> To avoid conflicts, Coder may also append a random word to the resulting
> username.

## OIDC Login Customization

If you'd like to change the OpenID Connect button text and/or icon, you can
configure them like so:

```dotenv
CODER_OIDC_SIGN_IN_TEXT="Sign in with Gitea"
CODER_OIDC_ICON_URL=https://gitea.io/images/gitea.png
```

To change the icon and text above the OpenID Connect button, see application
name and logo url in [appearance](../../setup/appearance.md) settings.

## Configure Refresh Tokens

By default, OIDC access tokens typically expire after a short period.
This is typically after one hour, but varies by provider.

Without refresh tokens, users will be automatically logged out when their access token expires.

Follow [Configure OIDC Refresh Tokens](./refresh-tokens.md) for provider-specific steps.

The general steps to configure persistent user sessions are:

1. Configure your Coder OIDC settings:

   For most providers, add the `offline_access` scope:

   ```dotenv
   CODER_OIDC_SCOPES=openid,profile,email,offline_access
   ```

   For Google, add auth URL parameters (`CODER_OIDC_AUTH_URL_PARAMS`) too:

   ```dotenv
   CODER_OIDC_SCOPES=openid,profile,email
   CODER_OIDC_AUTH_URL_PARAMS='{"access_type": "offline", "prompt": "consent"}'
   ```

1. Configure your identity provider to issue refresh tokens.

1. After configuration, have users log out and back in once to obtain refresh tokens

> [!IMPORTANT]
> Misconfigured refresh tokens can lead to frequent user authentication prompts.

## Disable Built-in Authentication

To remove email and password login, set the following environment variable on
your Coder deployment:

```dotenv
CODER_DISABLE_PASSWORD_AUTH=true
```

## SCIM

> [!IMPORTANT]
> SCIM is a Premium feature
> ([learn more](https://coder.com/pricing#compare-plans)).
>
> Coder's SCIM 2.0 implementation is not a fully certified or guaranteed
> implementation of the [SCIM 2.0 specification](https://datatracker.ietf.org/doc/html/rfc7644).
> It is intended to cover common user provisioning and deprovisioning flows
> with the major identity providers (Okta, Microsoft Entra ID, etc.). Specific
> attributes, endpoints, or behaviors required by your IdP may not be
> supported, and compatibility may change between releases. If you depend on
> a specific SCIM behavior, [contact us](https://coder.com/contact) before
> rolling it out broadly. See
> [coder/coder#15830](https://github.com/coder/coder/issues/15830) for
> tracked gaps and ongoing work.

Coder supports user provisioning and deprovisioning via SCIM 2.0 with header
authentication. Upon deactivation, users are
[suspended](../index.md#suspend-a-user) and are not deleted.
[Configure](../../setup/index.md) your SCIM application with an auth key and supply
it to the control plane.

```dotenv
CODER_SCIM_AUTH_HEADER="your-api-key"
```

### SCIM 2.0 handler

Coder includes an opt-in SCIM 2.0 handler that follows [RFC 7644](https://datatracker.ietf.org/doc/html/rfc7644) and has been verified against an external SCIM 2.0 compliance suite.
It supports the following:

- User provisioning and deprovisioning
- User listing

To opt in, set:

```dotenv
CODER_SCIM_USE_LEGACY=false
```

This is also available as the `--scim-use-legacy` server flag and the `scimUseLegacy` YAML option.
Changing it requires a restart of the control plane.

Behavior notes:

- Coder never hard-deletes users. `DELETE /scim/v2/Users/{id}` and deactivation (`active: false`) both [suspend](../index.md#suspend-a-user) the user.
- Re-activating or re-creating a previously suspended user places them in the dormant state, and they become active again on their next login.
- Usernames are immutable. Attempts to change `userName` via `PUT` or `PATCH` return a `mutability` error.

The SCIM 2.0 handler will eventually become the default behavior.

## TLS

If your OpenID Connect provider requires client TLS certificates for
authentication, you can configure them like so:

```dotenv
CODER_TLS_CLIENT_CERT_FILE=/path/to/cert.pem
CODER_TLS_CLIENT_KEY_FILE=/path/to/key.pem
```

## Next steps

- [Group Sync](../idp-sync.md)
- [Groups & Roles](../groups-roles.md)
- [Configure OIDC Refresh Tokens](./refresh-tokens.md)

---

# Google authentication (OIDC)

Source: https://coder.com/docs/admin/users/oidc-auth/google

This guide shows how to configure Coder to authenticate users with Google using OpenID Connect (OIDC).

## Prerequisites

- A Google Cloud project with the OAuth consent screen configured
- Permission to create OAuth 2.0 Client IDs in Google Cloud

## Step 1: Create an OAuth client in Google Cloud

1. Open Google Cloud Console → APIs & Services → Credentials → Create Credentials → OAuth client ID.
2. Application type: Web application.
3. Authorized redirect URIs: add your Coder callback URL:
   - `https://coder.example.com/api/v2/users/oidc/callback`
4. Save and note the Client ID and Client secret.

## Step 2: Configure Coder OIDC for Google

Set the following environment variables on your Coder deployment and restart Coder:

```dotenv
CODER_OIDC_ISSUER_URL=https://accounts.google.com
CODER_OIDC_CLIENT_ID=<client id>
CODER_OIDC_CLIENT_SECRET=<client secret>
# Restrict to one or more email domains (comma-separated)
CODER_OIDC_EMAIL_DOMAIN="example.com"
# Standard OIDC scopes for Google
CODER_OIDC_SCOPES=openid,profile,email
# Optional: customize the login button
CODER_OIDC_SIGN_IN_TEXT="Sign in with Google"
CODER_OIDC_ICON_URL=/icon/google.svg
```

> [!NOTE]
> The redirect URI must exactly match what you configured in Google Cloud.

## Enable refresh tokens (recommended)

Google uses auth URL parameters to issue refresh tokens. Configure:

```dotenv
# Keep standard scopes
CODER_OIDC_SCOPES=openid,profile,email
# Add Google-specific auth URL params
CODER_OIDC_AUTH_URL_PARAMS='{"access_type": "offline", "prompt": "consent"}'
```

After changing settings, users must log out and back in once to obtain refresh tokens.

Learn more in [Configure OIDC refresh tokens](./refresh-tokens.md).

## Troubleshooting

- "invalid redirect_uri": ensure the redirect URI in Google Cloud matches `https://<your-coder-host>/api/v2/users/oidc/callback`.
- Domain restriction: if users from unexpected domains can log in, verify `CODER_OIDC_EMAIL_DOMAIN`.
- Claims: to inspect claims returned by Google, see guidance in the [OIDC overview](./index.md#oidc-claims).

## See also

- [OIDC overview](./index.md)
- [Configure OIDC refresh tokens](./refresh-tokens.md)

---

# Microsoft Entra ID authentication (OIDC)

Source: https://coder.com/docs/admin/users/oidc-auth/microsoft

This guide shows how to configure Coder to authenticate users with Microsoft Entra ID using OpenID Connect (OIDC)

## Prerequisites

- A Microsoft Azure Entra ID Tenant
- Permission to create Applications in your Azure environment

## Step 1: Create an OAuth App Registration in Microsoft Azure

1. Open Microsoft Azure Portal (https://portal.azure.com) → Microsoft Entra ID → App Registrations → New Registration
2. Name: Name your application appropriately
3. Supported Account Types: Choose the appropriate radio button according to your needs. Most organizations will want to use the first one labeled "Accounts in this organizational directory only"
4. Select "Register"
5. On the next screen, select: "Certificates and Secrets"
6. Select "New Client Secret" and under description, enter an appropriate description. Then set an expiry and hit "Add" once it's created, copy the value and save it somewhere secure for the next step
7. Next, select the tab labeled "Token Configuration", then select "Add optional claim" and select the "ID" radio button, and finally check "upn" and hit "add" at the bottom
8. Then, select the button labeled "Add groups claim" and check "Security groups" and select "Save" at the bottom
9. Now, select the tab labeled "Authentication" and select "Add a platform", select "Web" and for the redirect URI enter your Coder callback URL, and then hit "Configure" at the bottom:
   - `https://coder.example.com/api/v2/users/oidc/callback`

## Step 2: Configure Coder OIDC for Microsoft Entra ID

Set the following environment variables on your Coder deployment and restart Coder:

```dotenv
CODER_OIDC_ISSUER_URL=https://login.microsoftonline.com/{tenant-id}/v2.0 # Replace {tenant-id} with your Azure tenant ID
CODER_OIDC_CLIENT_ID=<client id, located in "Overview">
CODER_OIDC_CLIENT_SECRET=<client secret, saved from step 6>
# Restrict to one or more email domains (comma-separated)
CODER_OIDC_EMAIL_DOMAIN="example.com"
CODER_OIDC_EMAIL_FIELD="upn" # This is set because EntraID typically uses .onmicrosoft.com domains by default, this should pull the user's username@domain email.
CODER_OIDC_GROUP_FIELD="groups" # This is for group sync / IdP Sync, a premium feature.
# Optional: customize the login button
CODER_OIDC_SIGN_IN_TEXT="Sign in with Microsoft Entra ID"
CODER_OIDC_ICON_URL=/icon/microsoft.svg
```

> [!NOTE]
> The redirect URI must exactly match what you configured in Microsoft Azure Entra ID

## Enable refresh tokens (recommended)

```dotenv
# Keep standard scopes
CODER_OIDC_SCOPES=openid,profile,email,offline_access
```

After changing settings, users must log out and back in once to obtain refresh tokens

Learn more in [Configure OIDC refresh tokens](./refresh-tokens.md).

## Troubleshooting

- "invalid redirect_uri": ensure the redirect URI in Azure Entra ID matches `https://<your-coder-host>/api/v2/users/oidc/callback`
- Domain restriction: if users from unexpected domains can log in, verify `CODER_OIDC_EMAIL_DOMAIN`
- Claims: to inspect claims returned by Microsoft, see guidance in the [OIDC overview](./index.md#oidc-claims)

## See also

- [OIDC overview](./index.md)
- [Configure OIDC refresh tokens](./refresh-tokens.md)

---

# Configure OIDC refresh tokens

Source: https://coder.com/docs/admin/users/oidc-auth/refresh-tokens

OIDC refresh tokens allow your Coder deployment to maintain user sessions beyond the initial access token expiration.
Without properly configured refresh tokens, users will be automatically logged out when their access token expires.
This is typically after one hour, but varies by provider, and can disrupt the user's workflow.

> [!IMPORTANT]
> Misconfigured refresh tokens can lead to frequent user authentication prompts.
>
> After the admin enables refresh tokens, all existing users must log out and back in again to obtain a refresh token.

<div class="tabs">

<!-- markdownlint-disable MD001 -->

### Azure AD

Go to the Azure Portal > **Azure Active Directory** > **App registrations** > Your Coder app and make the following changes:

1. In the **Authentication** tab:

   - **Platform configuration** > Web
   - Ensure **Allow public client flows** is `No` (Coder is confidential)
   - **Implicit grant / hybrid flows** can stay unchecked

1. In the **API permissions** tab:

   - Add the built-in permission `offline_access` under **Microsoft Graph** > **Delegated permissions**
   - Keep `openid`, `profile`, and `email`

1. In the **Certificates & secrets** tab:

   - Verify a Client secret (or certificate) is valid.
     Coder uses it to redeem refresh tokens.

1. In your [Coder configuration](../../../reference/cli/server/index.md#--oidc-auth-url-params), request the same scopes:

   ```dotenv
   CODER_OIDC_SCOPES=openid,profile,email,offline_access
   ```

1. Restart Coder and have users log out and back again for the changes to take effect.

   Alternatively, you can force a sign-out for all users with the
   [sign-out request process](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc#send-a-sign-out-request).

1. Azure issues rolling refresh tokens with a default absolute expiration of 90&nbsp;days and inactivity expiration of 24&nbsp;hours.

   You can adjust these settings under **Authentication methods** > **Token lifetime** (or use Conditional-Access policies in Entra ID).

You don't need to configure the 'Expose an API' section for refresh tokens to work.

Learn more in the [Microsoft Entra documentation](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols-oidc#enable-id-tokens).

### Google

To ensure Coder receives a refresh token when users authenticate with Google directly, set the `prompt` to `consent`
in the auth URL parameters (`CODER_OIDC_AUTH_URL_PARAMS`).
Without this, users will be logged out when their access token expires.

In your [Coder configuration](../../../reference/cli/server/index.md#--oidc-auth-url-params):

```dotenv
CODER_OIDC_SCOPES=openid,profile,email
CODER_OIDC_AUTH_URL_PARAMS='{"access_type": "offline", "prompt": "consent"}'
```

### Keycloak

The `access_type` parameter has two possible values: `online` and `offline`.
By default, the value is set to `offline`.

This means that when a user authenticates using OIDC, the application requests offline access to the user's resources,
including the ability to refresh access tokens without requiring the user to reauthenticate.

Add the `offline_access` scope to enable refresh tokens in your
[Coder configuration](../../../reference/cli/server/index.md#--oidc-auth-url-params):

```dotenv
CODER_OIDC_SCOPES=openid,profile,email,offline_access
CODER_OIDC_AUTH_URL_PARAMS='{"access_type":"offline"}'
```

### PingFederate

1. In PingFederate go to **Applications** > **OAuth Clients** > Your Coder client.

1. On the **Client** tab:

   - **Grant Types**: Enable `refresh_token`
   - **Allowed Scopes**: Add `offline_access` and keep `openid`, `profile`, and `email`

1. Optionally, in **Token Settings**

   - **Refresh Token Lifetime**: set a value that matches your security policy. Ping's default is 30&nbsp;days.
   - **Idle Timeout**: ensure it's more than or equal to the lifetime of the access token so that refreshes don't fail prematurely.

1. Save your changes in PingFederate.

1. In your [Coder configuration](../../../reference/cli/server/index.md#--oidc-scopes), add the `offline_access` scope:

   ```dotenv
   CODER_OIDC_SCOPES=openid,profile,email,offline_access
   ```

1. Restart your Coder deployment to apply these changes.

Users must log out and log in once to store their new refresh tokens.
After that, sessions should last until the Ping Federate refresh token expires.

Learn more in the [PingFederate documentation](https://docs.pingidentity.com/pingfederate/12.2/administrators_reference_guide/pf_configuring_oauth_clients.html).

</div>

## Confirm refresh token configuration

To verify refresh tokens are working correctly:

1. Check that your OIDC configuration includes the required refresh token parameters:

     - `offline_access` scope for most providers
     - `"access_type": "offline"` for Google

1. Verify provider-specific token configuration:

   <div class="tabs">

   ### Azure AD

   Use [jwt.ms](https://jwt.ms) to inspect the `id_token` and ensure the `rt_hash` claim is present.
   This shows that a refresh token was issued.

   ### Google

   If users are still being logged out periodically, check your client configuration in Google Cloud Console.

   ### Keycloak

   Review Keycloak sessions for the presence of refresh tokens.

   ### Ping Federate

   - Verify the client sent `offline_access` in the `grantedScopes` portion of the ID token.
   - Confirm `refresh_token` appears in the `grant_types` list returned by `/pf-admin-api/v1/oauth/clients/{id}`.

   </div>

1. Verify users can stay logged in beyond the identity provider's access token expiration period (typically 1&nbsp;hour).

1. Monitor Coder logs for `failed to renew OIDC token: token has expired` messages.
   There should not be any.

If all verification steps pass successfully, your refresh token configuration is working properly.

## Troubleshooting OIDC Refresh Tokens

### Users are logged out too frequently

**Symptoms**:

- Users experience session timeouts and must re-authenticate.
- Session timeouts typically occur after the access token expiration period (varies by provider, commonly 1&nbsp;hour).

**Causes**:

- Missing required refresh token configuration:
  - `offline_access` scope for most providers
  - `"access_type": "offline"` for Google
- Provider not correctly configured to issue refresh tokens.
- User has not logged in since refresh token configuration was added.

**Solution**:

- For most providers, add `offline_access` to your `CODER_OIDC_SCOPES` configuration.
  - `"access_type": "offline"` for Google
- Configure your identity provider according to the provider-specific instructions above.
- Have users log out and log in again to obtain refresh tokens.
  Look for entries containing `failed to renew OIDC token` which might indicate specific provider issues.

### Refresh tokens don't work after configuration change

**Symptoms**:

- Session timeouts continue despite refresh token configuration and users re-authenticating.
- Some users experience frequent logouts.

**Cause**:

- Existing user sessions don't have refresh tokens stored.
- Configuration may be incomplete.

**Solution**:

- Users must log out and log in again to get refresh tokens stored in the database.
- Verify you've correctly configured your provider as described in the configuration steps above.
- Check Coder logs for specific error messages related to token refresh.

Users might get logged out again before the new configuration takes effect completely.

---

# GitHub

Source: https://coder.com/docs/admin/users/github-auth

By default, new Coder deployments use a Coder-managed GitHub app to authenticate
users.
We provide it for convenience, allowing you to experiment with Coder
without setting up your own GitHub OAuth app.

If you authenticate with it, you grant the control plane read access to your
GitHub user email and other metadata listed during the authentication flow.

This access is necessary for the control plane to complete the authentication
process.
To the best of our knowledge, Coder, the company, does not gain access
to this data by administering the GitHub app.

## Default Configuration

> [!IMPORTANT]
> Installation of the default GitHub app grants Coder (the company) access to your organization's GitHub data.
>
> For production environments, we strongly recommend that you
> [configure your own GitHub OAuth app](#step-1-configure-the-oauth-application-in-github)
> to ensure that your data is not shared with Coder (the company).

To use the default configuration:

1. [Install the GitHub app](https://github.com/apps/coder/installations/select_target)
   in any GitHub organization that you want to use with Coder.

   The default GitHub app requires [device flow](#device-flow) to authenticate.
   This is enabled by default when using the default GitHub app.
   If you disable device flow using `CODER_OAUTH2_GITHUB_DEVICE_FLOW=false`, it will be ignored.

1. By default, only the admin user can sign up.
   To allow additional users to sign up with GitHub, add:

   ```sh
   CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS=true
   ```

1. (Optional) If you want to limit sign-ups to specific GitHub organizations, set:

   ```sh
   CODER_OAUTH2_GITHUB_ALLOWED_ORGS="your-org"
   ```

## Disable the Default GitHub App

You can disable the default GitHub app by [configuring your own app](#step-1-configure-the-oauth-application-in-github)
or by adding the following environment variable to your [control plane configuration](../../reference/cli/server/index.md#options):

```sh
CODER_OAUTH2_GITHUB_DEFAULT_PROVIDER_ENABLE=false
```

> [!NOTE]
> After you disable the default GitHub provider, the **Sign in with GitHub** button
> might still appear on your login page even though the authentication flow is disabled.
>
> To completely hide the GitHub sign-in button, you must disable the default provider
> and ensure you don't have a custom GitHub OAuth app configured.

## Step 1: Configure the OAuth application in GitHub

1. [Register a GitHub OAuth app](https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/).

1. GitHub will ask you for the following Coder parameters:

   - **Homepage URL**: Set to your Coder deployment's
     [`CODER_ACCESS_URL`](../../reference/cli/server/index.md#--access-url) (e.g.
     `https://coder.domain.com`)
   - **User Authorization Callback URL**: Set to `https://coder.domain.com`

     If you want to allow multiple Coder deployments hosted on subdomains, such as
     `coder1.domain.com`, `coder2.domain.com`, to authenticate with the
     same GitHub OAuth app, then you can set **User Authorization Callback URL** to
     the `https://domain.com`

1. Take note of the Client ID and Client Secret generated by GitHub.
   You will use these values in the next step.

1. Coder needs permission to access user email addresses.

   Find the **Account Permissions** settings for your app and select **read-only** for **Email addresses**.

## Step 2: Configure Coder with the OAuth credentials

The control plane reads these settings from environment variables. Set them
wherever your deployment manages environment variables. For example, use
Helm `values.yaml` for Kubernetes or `/etc/coder.d/coder.env` for a system
service.

**Kubernetes (Helm):** set the variables under `coder.env` in your
`values.yaml`:

```yaml
coder:
  env:
    - name: CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS
      value: "true"
    - name: CODER_OAUTH2_GITHUB_CLIENT_ID
      value: "533...des"
    - name: CODER_OAUTH2_GITHUB_CLIENT_SECRET
      value: "G0CSP...7qSM"
    # If setting allowed orgs, comment out CODER_OAUTH2_GITHUB_ALLOW_EVERYONE and its value
    - name: CODER_OAUTH2_GITHUB_ALLOWED_ORGS
      value: "your-org"
    # If allowing everyone, comment out CODER_OAUTH2_GITHUB_ALLOWED_ORGS and its value
    #- name: CODER_OAUTH2_GITHUB_ALLOW_EVERYONE
    #  value: "true"
```

Then apply the change with `helm upgrade`:

```sh
helm upgrade <release-name> coder-v2/coder -n <namespace> -f values.yaml
```

**System service:** add the variables to `/etc/coder.d/coder.env`:

```sh
CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS=true
CODER_OAUTH2_GITHUB_ALLOWED_ORGS="your-org"
CODER_OAUTH2_GITHUB_CLIENT_ID="8d1...e05"
CODER_OAUTH2_GITHUB_CLIENT_SECRET="57ebc9...02c24c"
```

Then restart Coder with `sudo service coder restart`.

> [!TIP]
> To allow everyone to sign up using GitHub, set:
>
> ```shell
> CODER_OAUTH2_GITHUB_ALLOW_EVERYONE=true
> ```

For GitHub Enterprise support, also set
`CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL`.

> [!NOTE]
> Every option above also has an equivalent CLI flag (for example,
> `CODER_OAUTH2_GITHUB_CLIENT_ID` becomes `--oauth2-github-client-id`).
> CLI flags are convenient for ad-hoc invocations of `coder server` during
> local development. For production deployments, prefer environment
> variables so the configuration lives with the container, Helm chart, or
> service unit that manages Coder. See the
> [configuration reference](../setup/configuration-reference.md) for the
> full mapping between environment variables and flags.

We recommend requiring and auditing MFA usage for all users in your GitHub organizations.
This can be enforced from the organization settings page in the **Authentication security** sidebar tab.

## Device Flow

Coder supports
[device flow](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#device-flow)
for GitHub OAuth.
This is enabled by default for the default GitHub app and cannot be disabled for that app.

For your own custom GitHub OAuth app, you can enable device flow by setting:

```sh
CODER_OAUTH2_GITHUB_DEVICE_FLOW=true
```

Device flow is optional for custom GitHub OAuth apps.
We generally recommend using the standard OAuth flow instead, as it is more convenient for end users.

> [!NOTE]
> If you're using the default GitHub app, device flow is always enabled regardless of
> the `CODER_OAUTH2_GITHUB_DEVICE_FLOW` setting.

---

# Password Authentication

Source: https://coder.com/docs/admin/users/password-auth

Coder has password authentication enabled by default. The account created during
setup is a username/password account.

## Disable password authentication

To disable password authentication, use the
[`CODER_DISABLE_PASSWORD_AUTH`](../../reference/cli/server/index.md#--disable-password-auth)
flag on the control plane.

## Restore the `Owner` user

If you remove the admin user account (or forget the password), you can run the
[`coder server create-admin-user`](../../reference/cli/server/create-admin-user.md)command
on your server.

> [!IMPORTANT]
> You must run this command on the same machine running the control plane.
> If you are running Coder on Kubernetes, this means using
> [kubectl exec](https://kubernetes.io/docs/reference/kubectl/generated/kubectl_exec/)
> to exec into the pod.

## Reset a user's password

An admin must reset passwords on behalf of users. This can be done in the web UI
in the Users page or CLI:
[`coder reset-password`](../../reference/cli/reset-password.md)

---

# Headless Authentication

Source: https://coder.com/docs/admin/users/headless-auth

> [!NOTE]
> Creating service accounts requires a [Premium license](https://coder.com/pricing).

Service accounts are headless user accounts that cannot use the web UI to log in
to Coder. This is useful for creating accounts for automated systems, such as
CI/CD pipelines or for users who only consume Coder via another client/API. Service accounts do not have passwords or associated email addresses.

You must have the User Admin role or above to create service accounts.

## Create a service account

<div class="tabs">

## CLI

Use the `--service-account` flag to create a dedicated service account:

```sh
coder users create \
  --username="coder-bot" \
  --service-account
```

## UI

Navigate to **Deployment** > **Users** > **New user**, then select **Service account** as the login type.

![Create a user via the UI](../../images/admin/users/headless-user.png)

</div>

## Authenticate as a service account

To make API or CLI requests on behalf of the headless user, learn how to
[generate API tokens on behalf of a user](./sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-another-user).

---

# Groups and roles (Premium)

Source: https://coder.com/docs/admin/users/groups-roles

Groups and roles can be manually assigned in Coder. For production deployments,
these can also be [managed and synced by the identity provider](./idp-sync.md).

## Groups

> [!NOTE]
> Groups require a
> [Premium license](https://coder.com/pricing#compare-plans).
> For more details, [contact your account team](https://coder.com/contact).

Groups are logical segmentations of users in Coder and can be used to control
which templates developers can use. For example:

- Users within the `devops` group can access the `AWS-VM` template
- Users within the `data-science` group can access the `Jupyter-Kubernetes`
  template

## Roles

Roles determine which actions users can take within the platform.
The roles in the following table apply across the whole deployment.
Organizations have their own roles.
Refer to [Organization roles](#organization-roles) for more information.

|                                                                          | Auditor | User Admin | Template Admin | Owner |
|--------------------------------------------------------------------------|---------|------------|----------------|-------|
| Add and remove Users                                                     |         | ✅          |                | ✅     |
| Manage groups (premium)                                                  |         | ✅          |                | ✅     |
| Change User roles                                                        |         |            |                | ✅     |
| Manage **ALL** Templates                                                 |         |            | ✅              | ✅     |
| View **ALL** Workspaces                                                  |         |            | ✅              | ✅     |
| Update and delete **ALL** Workspaces                                     |         |            |                | ✅     |
| Run [external provisioners](../../install/operate/provisioners/index.md) |         |            | ✅              | ✅     |
| Execute and use **ALL** Workspaces                                       |         |            |                | ✅     |
| View all user operation [Audit Logs](../security/audit-logs.md)          | ✅       |            |                | ✅     |

A user may have one or more roles.
Every user also holds an implicit Member role that covers their own account, such as reading their profile and managing their tokens.

The Member role doesn't grant workspace access on its own.
The ability to create and use workspaces comes from the organization's default member roles, which include Organization Workspace Access by default.
Refer to [Default member roles](./organizations.md#default-member-roles) for how to remove workspace operations from the default member set.

The preceding table describes a default deployment.
A deployment that sets `CODER_DISABLE_OWNER_WORKSPACE_ACCESS` removes the Owner role's SSH, application, and terminal access to other users' workspaces.
Owners keep that access to workspaces they own.
Refer to [`--disable-owner-workspace-access`](../../reference/cli/server/index.md#--disable-owner-workspace-access) for the flag, environment variable, and YAML forms.

## Organization roles

Organization roles apply inside a single [organization](./organizations.md) rather than across the deployment.
A user who belongs to more than one organization can hold different organization roles in each one.
Assign organization roles from **Admin settings** > **Organizations** > **Members**, or sync them from your identity provider with [IdP sync](./idp-sync.md).

Coder ships the following organization roles:

- **Organization Admin**: manages the organization's templates, provisioners, groups, members, and organization role assignments.
- **Organization User Admin**: manages the organization's members, groups, and role assignments, including its IdP sync settings.
- **Organization Template Admin**: manages the organization's templates and provisioners, and reads its workspaces.
- **Organization Auditor**: reads the organization's audit logs and connection logs, along with the resources those logs reference.
- **Organization Workspace Access**: creates and operates the user's own workspaces in the organization.
- **Organization Workspace Creation Ban**: blocks creating and deleting workspaces in the organization, and overrides any role that would otherwise allow it.
- **Coder Agents User**: uses [Coder Agents](../../ai-coder/agents/index.md) in the organization. Members other than service accounts hold this role through the organization's [default member roles](./organizations.md#default-member-roles) unless an administrator removes it.

Organization Admin doesn't include SSH, application, or terminal access to workspaces other members own.
A user with that role can read, build, stop, and delete those workspaces.
Connecting to one requires access granted through [workspace sharing](../../user-guides/shared-workspaces.md).

Every member of an organization also holds an implicit organization membership role that the dashboard doesn't display.
That role carries the smallest permission set a member needs, such as reading the organization and their own membership record.
Service accounts hold an equivalent implicit role.

## Custom roles

> [!NOTE]
> Custom roles are a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Starting in v2.16.0, Premium Coder deployments can configure custom roles on the
[Organization](./organizations.md) level. You can create and assign custom roles
in the dashboard under **Organizations** -> **My Organization** -> **Roles**.

![Custom roles](../../images/admin/users/roles/custom-roles.PNG)

### Example roles

- The `Banking Compliance Auditor` custom role cannot create workspaces, but can
  read template source code and view audit logs
- The `Organization Lead` role can access user workspaces for troubleshooting
  purposes, but cannot edit templates
- The `Platform Member` role cannot edit or create workspaces as they are
  created via a third-party system

Custom roles can also be applied to
[headless user accounts](./headless-auth.md):

- A `Health Check` role can view deployment status but cannot create workspaces,
  manage templates, or view users
- A `CI` role can update manage templates but cannot create workspaces or view
  users

<a id="creating-custom-roles"></a>

### Create custom roles

Selecting "Create custom role" opens a UI to select the desired permissions for a given persona.

![Creating a custom role](../../images/admin/users/roles/creating-custom-role.PNG)

From there, you can assign the custom role to any user in the organization under
the **Users** settings in the dashboard.

![Assigning a custom role](../../images/admin/users/roles/assigning-custom-role.PNG)

Note that these permissions only apply to the scope of an
[organization](./organizations.md), not across the deployment.

### Security notes

A malicious Template Admin could write a template that executes commands on the
host (or `coder server` container), which potentially escalates their privileges
or shuts down the control plane. To avoid this, run
[external provisioners](../../install/operate/provisioners/index.md).

In low-trust environments, we do not recommend giving users direct access to
edit templates. Instead, use
[CI/CD pipelines to update templates](../templates/managing-templates/change-management.md)
with proper security scans and code reviews in place.

---

# IdP Sync

Source: https://coder.com/docs/admin/users/idp-sync

<!-- markdownlint-disable MD024 -->
> [!NOTE]
> IdP sync is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

IdP (Identity provider) sync allows you to use OpenID Connect (OIDC) to
synchronize Coder groups, roles, and organizations based on claims from your IdP.

## Prerequisites

### Confirm that OIDC provider sends claims

To confirm that your OIDC provider is sending claims, log in with OIDC and visit
the following URL with an `Owner` account:

```txt
https://[coder.example.com]/api/v2/debug/[your-username]/debug-link
```

You should see a field in either `id_token_claims`, `user_info_claims` or
both followed by a list of the user's OIDC groups in the response.

This is the [claim](https://openid.net/specs/openid-connect-core-1_0.html#Claims)
sent by the OIDC provider.

Depending on the OIDC provider, this claim might be called something else.
Common names include `groups`, `memberOf`, and `roles`.

See the [troubleshooting section](#troubleshooting-grouproleorganization-sync)
for help troubleshooting common issues.

## Group Sync

If your OpenID Connect provider supports group claims, you can configure Coder
to synchronize groups in your auth provider to groups within Coder. To enable
group sync, ensure that the `groups` claim is being sent by your OpenID
provider. You might need to request an additional
[scope](../../reference/cli/server/index.md#--oidc-scopes) or additional configuration
on the OpenID provider side.

If group sync is enabled, the user's groups will be controlled by the OIDC
provider. This means manual group additions/removals will be overwritten on the
next user login.

For deployments with multiple [organizations](./organizations.md), configure
group sync for each organization.

<div class="tabs">

### Dashboard

1. Fetch the corresponding group IDs using the following endpoint:

   ```txt
   https://[coder.example.com]/api/v2/groups
   ```

1. As an Owner or Organization Admin, go to **Admin settings**, select
   **Organizations**, then **IdP Sync**:

   ![IdP Sync - Group sync](../../images/admin/users/organizations/group-sync-empty.png)

1. Enter the **Group sync field** and an optional **Regex filter**, then select
   **Save**.

1. Select **Auto create missing groups** to automatically create groups
   returned by the OIDC provider if they do not exist in Coder.

1. Enter the **IdP group name** and **Coder group**, then **Add IdP group**.

### CLI

1. Confirm you have the [Coder CLI](../../install/index.md) installed and are
   logged in with a user who is an Owner or has an Organization Admin role.

1. To fetch the current group sync settings for an organization, run the
   following:

   ```sh
   coder organizations settings show group-sync \
     --org <org-name> \
     > group-sync.json
   ```

   The default for an organization looks like this:

   ```json
   {
       "field": "",
       "mapping": null,
       "regex_filter": null,
       "auto_create_missing_groups": false
   }
   ```

Below is an example that uses the `groups` claim and maps all groups prefixed by
`coder-` into Coder:

```json
{
    "field": "groups",
    "mapping": null,
    "regex_filter": "^coder-.*$",
    "auto_create_missing_groups": true
}
```

You must specify Coder group IDs instead of group names.
You can find the ID for a corresponding group by visiting
`https://coder.example.com/api/v2/groups`.

Here is another example which maps `coder-admins` from the identity provider to
two groups in Coder and `coder-users` from the identity provider to another
group:

```json
{
    "field": "groups",
    "mapping": {
        "coder-admins": [
            "2ba2a4ff-ddfb-4493-b7cd-1aec2fa4c830",
            "93371154-150f-4b12-b5f0-261bb1326bb4"
        ],
        "coder-users": ["2f4bde93-0179-4815-ba50-b757fb3d43dd"]
    },
    "regex_filter": null,
    "auto_create_missing_groups": false
}
```

To set these group sync settings, use the following command:

```sh
coder organizations settings set group-sync \
  --org <org-name> \
  < group-sync.json
```

Visit the Coder UI to confirm these changes:

![IdP Sync](../../images/admin/users/organizations/group-sync.png)

### Server Flags

> [!NOTE]
> Use server flags only with Coder deployments with a single organization.
> You can use the dashboard to configure group sync instead.

1. Configure the control plane to read groups from the claim name with the
   [OIDC group field](../../reference/cli/server/index.md#--oidc-group-field) server
   flag:

   - Environment variable:

     ```sh
     CODER_OIDC_GROUP_FIELD=groups
     ```

   - As a flag:

     ```sh
     --oidc-group-field groups
     ```

1. On login, users will automatically be assigned to groups that have matching
   names in Coder and removed from groups that the user no longer belongs to.

1. For cases when an OIDC provider only returns group IDs or you want to have
   different group names in Coder than in your OIDC provider, you can configure
   mapping between the two with the
   [OIDC group mapping](../../reference/cli/server/index.md#--oidc-group-mapping) server
   flag:

   - Environment variable:

     ```sh
     CODER_OIDC_GROUP_MAPPING='{"myOIDCGroupID": "myCoderGroupName"}'
     ```

   - As a flag:

     ```sh
     --oidc-group-mapping '{"myOIDCGroupID": "myCoderGroupName"}'
     ```

   Below is an example mapping in the Coder Helm chart:

   ```yaml
   coder:
     env:
       - name: CODER_OIDC_GROUP_MAPPING
         value: >
           {"myOIDCGroupID": "myCoderGroupName"}
   ```

   From this example, users that belong to the `myOIDCGroupID` group in your
   OIDC provider will be added to the `myCoderGroupName` group in Coder.

</div>

### Group allowlist

You can limit which groups from your identity provider can log in to Coder with
[CODER_OIDC_ALLOWED_GROUPS](../../reference/cli/server/index.md#--oidc-allowed-groups).
Users who are not in a matching group will see the following error:

<img height="412px" src="../../images/admin/group-allowlist.png" alt="Unauthorized group error" align="center" />

## Role Sync

If your OpenID Connect provider supports roles claims, you can configure Coder
to synchronize roles in your auth provider to roles within Coder.

For deployments with multiple [organizations](./organizations.md), configure
role sync at the organization level.

<div class="tabs">

### Dashboard

1. As an Owner or Organization Admin, go to **Admin settings**, select
   **Organizations**, then **IdP Sync**.

1. Select the **Role sync settings** tab:

   ![IdP Sync - Role sync settings](../../images/admin/users/organizations/role-sync-empty.png)

1. Enter the **Role sync field**, then select **Save**.

1. Enter the **IdP role name** and **Coder role**, then **Add IdP role**.

   To add a new custom role, select **Roles** from the sidebar, then
   **Create custom role**.

   Visit the [groups and roles documentation](./groups-roles.md) for more information.

### CLI

1. Confirm you have the [Coder CLI](../../install/index.md) installed and are
   logged in with a user who is an Owner or has an Organization Admin role.

1. To fetch the current role sync settings for an organization, run the
   following:

   ```sh
   coder organizations settings show role-sync \
     --org <org-name> \
     > role-sync.json
   ```

   The default for an organization looks like this:

   ```json
   {
       "field": "",
       "mapping": null
   }
   ```

Below is an example that uses the `roles` claim and maps `coder-admins` from the
IdP as an `Organization Admin` and also maps to a custom `provisioner-admin`
role:

```json
{
    "field": "roles",
    "mapping": {
        "coder-admins": ["organization-admin"],
        "infra-admins": ["provisioner-admin"]
    }
}
```

> [!NOTE]
> Be sure to use the `name` field for each role, not the display name.
> Use `coder organization roles show --org=<your-org>` to see roles for your organization.

To set these role sync settings, use the following command:

```sh
coder organizations settings set role-sync \
  --org <org-name> \
  < role-sync.json
```

Visit the Coder UI to confirm these changes:

![IdP Sync](../../images/admin/users/organizations/role-sync.png)

### Server Flags

> [!NOTE]
> Use server flags only with Coder deployments with a single organization.
> You can use the dashboard to configure role sync instead.

1. Configure the control plane to read groups from the claim name with the
   [OIDC role field](../../reference/cli/server/index.md#--oidc-user-role-field)
   server flag:

1. Set the following in your control plane [configuration](../setup/index.md).

   ```dotenv
    # Depending on your identity provider configuration, you may need to explicitly request a "roles" scope
   CODER_OIDC_SCOPES=openid,profile,email,offline_access,roles

   # The following fields are required for role sync:
   CODER_OIDC_USER_ROLE_FIELD=roles
   CODER_OIDC_USER_ROLE_MAPPING='{"TemplateAuthor":["template-admin","user-admin"]}'
   ```

One role from your identity provider can be mapped to many roles in Coder. The
example above maps to two roles in Coder.

</div>

## Organization Sync

If your OpenID Connect provider supports groups/role claims, you can configure
Coder to synchronize claims in your auth provider to organizations within Coder.

Viewing and editing the organization settings requires deployment admin
permissions (UserAdmin or Owner).

Organization sync works across all organizations. On user login, the sync will
add and remove the user from organizations based on their IdP claims. After the
sync, the user's state should match that of the IdP.

You can initiate an organization sync through the Coder dashboard or CLI:

<div class="tabs">

### Dashboard

1. Fetch the corresponding organization IDs using the following endpoint:

   ```txt
   https://[coder.example.com]/api/v2/organizations
   ```

1. As a Coder organization user admin or site-wide user admin, go to
   **Admin settings** > **Deployment** and select **IdP organization sync**.

1. In the **Organization sync field** text box, enter the organization claim,
   then select **Save**.

   Users are automatically added to the default organization.

   Do not disable **Assign Default Organization**. If you disable the default
   organization, the system will remove users who are already assigned to it.

1. Enter an IdP organization name and Coder organization(s), then select **Add
   IdP organization**:

   ![IdP organization sync](../../images/admin/users/organizations/idp-org-sync.png)

### CLI

Use the Coder CLI to show and adjust the settings.

These deployment-wide settings are stored in the database. After you change the
settings, a user's memberships will update when they log out and log back in.

1. Show the current settings:

   ```console
   coder organization settings show org-sync
   {
      "field": "organizations",
      "mapping": {
         "product": ["868e9b76-dc6e-46ab-be74-a891e9bd784b", "cbdcf774-9412-4118-8cd9-b3f502c84dfb"]
      },
      "organization_assign_default": true
   }
   ```

1. Update with the JSON payload. In this example, `settings.json` contains the
   payload:

   ```console
   coder organization settings set org-sync < settings.json
   {
      "field": "organizations",
      "mapping": {
         "product": [
            "868e5b23-dc6e-46ab-be74-a891e9bd784b",
            "cbdcf774-4123-4118-8cd9-b3f502c84dfb"
         ],
         "sales": [
            "d79144d9-b30a-555a-9af8-7dac83b2q4ec"
         ]
      },
      "organization_assign_default": true
   }
   ```

   Analyzing the JSON payload:

   | Field                       | Explanation                                                                                                                                                                                                                                                                              |
   |:----------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
   | field                       | If this field is the empty string `""`, then org-sync is disabled. <br /> Org memberships must be manually configured through the UI or API.                                                                                                                                             |
   | mapping                     | Mapping takes a claim from the IdP, and associates it with 1 or more organizations by UUID. <br /> No validation is done, so you can put UUID's of orgs that do not exist (a noop). The UI picker will allow selecting orgs from a drop down, and convert it to a UUID for you.          |
   | organization_assign_default | This setting exists for maintaining backwards compatibility with single org deployments, either through their upgrade, or in perpetuity. <br /> If this is set to 'true', all users will always be assigned to the default organization regardless of the mappings and their IdP claims. |

</div>

## Troubleshooting group/role/organization sync

Some common issues when enabling group, role, or organization sync.

### General guidelines

If you are running into issues with a sync:

1. View your `coderd` logs and enable
   [verbose mode](../../reference/cli/index.md#-v---verbose).

1. To reduce noise, you can filter for only logs related to group/role sync:

   ```sh
   CODER_LOG_FILTER=".*userauth.*|.*groups returned.*"
   ```

1. Restart the control plane after changing these configuration values.

1. Attempt to log in, preferably with a user who has the `Owner` role.

The logs for a successful sync look like this (human-readable):

```sh
[debu]  coderd.userauth: got oidc claims  request_id=49e86507-6842-4b0b-94d4-f245e62e49f3  source=id_token  claim_fields="[aio aud email exp groups iat idp iss name nbf oid preferred_username rh sub tid uti ver]"  blank=[]

[debu]  coderd.userauth: got oidc claims  request_id=49e86507-6842-4b0b-94d4-f245e62e49f3  source=userinfo  claim_fields="[email family_name given_name name picture sub]"  blank=[]

[debu]  coderd.userauth: got oidc claims  request_id=49e86507-6842-4b0b-94d4-f245e62e49f3  source=merged  claim_fields="[aio aud email exp family_name given_name groups iat idp iss name nbf oid picture preferred_username rh sub tid uti ver]"  blank=[]

[debu]  coderd: groups returned in oidc claims  request_id=49e86507-6842-4b0b-94d4-f245e62e49f3  email=ben@coder.com  username=ben  len=3  groups="[c8048e91-f5c3-47e5-9693-834de84034ad 66ad2cc3-a42f-4574-a281-40d1922e5b65 70b48175-107b-4ad8-b405-4d888a1c466f]"
```

To view the full claim, the Owner role can visit this endpoint on their Coder
deployment after logging in:

```sh
https://[coder.example.com]/api/v2/debug/[username]/debug-link
```

### User not being assigned / Group does not exist

If you want Coder to create groups that do not exist, you can set the following
environment variable.

If you enable this, your OIDC provider might be sending over many unnecessary
groups. Use filtering options on the OIDC provider to limit the groups sent over
to prevent creating excess groups.

```dotenv
# as an environment variable
CODER_OIDC_GROUP_AUTO_CREATE=true
```

```sh
# as a flag
--oidc-group-auto-create=true
```

A basic regex filtering option on the Coder side is available. This is applied
**after** the group mapping (`CODER_OIDC_GROUP_MAPPING`), meaning if the group
is remapped, the remapped value is tested in the regex. This is useful if you
want to filter out groups that do not match a certain pattern. For example, if
you want to only allow groups that start with `my-group-` to be created, you can
set the following environment variable.

```dotenv
# as an environment variable
CODER_OIDC_GROUP_REGEX_FILTER="^my-group-.*$"
```

```sh
# as a flag
--oidc-group-regex-filter="^my-group-.*$"
```

### Invalid Scope

If you see an error like the following, you may have an invalid scope.

```console
The application '<oidc_application>' asked for scope 'groups' that doesn't exist on the resource...
```

This can happen because the identity provider has a different name for the
scope. For example, Azure AD uses `GroupMember.Read.All` instead of `groups`.
You can find the correct scope name in the IdP's documentation. Some IdPs allow
configuring the name of this scope.

The solution is to update the value of `CODER_OIDC_SCOPES` to the correct value
for the identity provider.

### No `group` claim in the `got oidc claims` log

Steps to troubleshoot.

1. Ensure the user is a part of a group in the IdP. If the user has 0 groups, no
   `groups` claim will be sent.
2. Check if another claim appears to be the correct claim with a different name.
   A common name is `memberOf` instead of `groups`. If this is present, update
   `CODER_OIDC_GROUP_FIELD=memberOf`.
3. Make sure the number of groups being sent is under the limit of the IdP. Some
   IdPs will return an error, while others will just omit the `groups` claim. A
   common solution is to create a filter on the identity provider that returns
   less than the limit for your IdP.
   - [Azure AD limit is 200, and omits groups if exceeded.](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/connect/how-to-connect-fed-group-claims#options-for-applications-to-consume-group-information)
   - [Okta limit is 100, and returns an error if exceeded.](https://developer.okta.com/docs/reference/api/oidc/#scope-dependent-claims-not-always-returned)

## Provider-Specific Guides

<div class="tabs">

### Active Directory Federation Services (ADFS)

> [!NOTE]
> Tested on ADFS 4.0, Windows Server 2019

1. In your Federation Server, create a new application group for Coder.
   Follow the steps as described in the [Windows Server documentation]
   (https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/development/msal/adfs-msal-web-app-web-api#app-registration-in-ad-fs).

   - **Server Application**: Note the Client ID.
   - **Configure Application Credentials**: Note the Client Secret.
   - **Configure Web API**: Set the Client ID as the relying party identifier.
   - **Application Permissions**: Allow access to the claims `openid`, `email`,
     `profile`, and `allatclaims`.

1. Visit your ADFS server's `/.well-known/openid-configuration` URL and note the
   value for `issuer`.

   This will look something like
   `https://adfs.corp/adfs/.well-known/openid-configuration`.

1. In Coder's configuration file (or Helm values as appropriate), set the
   following environment variables or their corresponding CLI arguments:

   - `CODER_OIDC_ISSUER_URL`: `issuer` value from the previous step.
   - `CODER_OIDC_CLIENT_ID`: Client ID from step 1.
   - `CODER_OIDC_CLIENT_SECRET`: Client Secret from step 1.
   - `CODER_OIDC_AUTH_URL_PARAMS`: set to

     ```json
     {"resource":"$CLIENT_ID"}
     ```

     Where `$CLIENT_ID` is the Client ID from step 1.
     Consult the Microsoft [AD FS OpenID Connect/OAuth flows and Application Scenarios documentation](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/overview/ad-fs-openid-connect-oauth-flows-scenarios#:~:text=scope%E2%80%AFopenid.-,resource,-optional) for more information.

     This is required for the upstream OIDC provider to return the requested
     claims.

   - `CODER_OIDC_IGNORE_USERINFO`: Set to `true`.

1. Configure
   [Issuance Transform Rules](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-rule-to-send-ldap-attributes-as-claims)
   on your Federation Server to send the following claims:

   - `preferred_username`: You can use e.g. "Display Name" as required.
   - `email`: You can use e.g. the LDAP attribute "E-Mail-Addresses" as
     required.
   - `email_verified`: Create a custom claim rule:

     ```json
     => issue(Type = "email_verified", Value = "true")
     ```

   - (Optional) If using Group Sync, send the required groups in the configured
     groups claim field.
     Use [this answer from Stack Overflow](https://stackoverflow.com/a/55570286) for an example.

</div>

## Next Steps

- [Configure OIDC Refresh Tokens](./oidc-auth/refresh-tokens.md)
- [Organizations](./organizations.md)
- [Groups & Roles](./groups-roles.md)

---

# Organizations (Premium)

Source: https://coder.com/docs/admin/users/organizations

> [!NOTE]
> Organizations requires a
> [Premium license](https://coder.com/pricing#compare-plans). For more details,
> [contact your account team](https://coder.com/contact).

Organizations can be used to segment and isolate resources inside a Coder
deployment for different user groups or projects.

## Example

Here is an example of how one could use organizations to run a Coder deployment
with multiple platform teams, all with unique resources:

![Organizations Example](../../images/admin/users/organizations/diagram.png)

For more information about how to use organizations, visit the
[organizations best practices](../../tutorials/best-practices/organizations.md)
guide.

## The default organization

All Coder deployments start with one organization called `coder`. All new users
are added to this organization by default.

To edit the organization details, select **Admin settings** from the top bar, then
**Organizations**:

<img height="255px" src="../../images/admin/users/organizations/admin-settings-orgs.png" alt="Organizations Menu" align="center" />

From there, you can manage the name, icon, description, users, and groups:

![Organization Settings](../../images/admin/users/organizations/default-organization-settings.png)

## Additional organizations

Any additional organizations have unique admins, users, templates, provisioners,
groups, and workspaces. Each organization must have at least one dedicated
[provisioner](../../install/operate/provisioners/index.md) since the built-in provisioners only apply to
the default organization.

You can configure [organization/role/group sync](./idp-sync.md) from your
identity provider to avoid manually assigning users to organizations.

## How to create an organization

### Prerequisites

- Coder v2.16+ deployment with Premium license and Organizations enabled
  ([contact your account team](https://coder.com/contact)) for more details.
- User with `Owner` role

### 1. Create the organization

To create a new organization:

1. Select **Admin settings** from the top bar, then **Organizations**.

1. Select the current organization to expand the organizations dropdown, then select **Create Organization**:

   <img height="212px" src="../../images/admin/users/organizations/org-dropdown-create.png" alt="Organizations dropdown and Create Organization" align="center" />

1. Enter the details and select **Save** to continue:

   <img height="579px" src="../../images/admin/users/organizations/new-organization.png" alt="New Organization" align="center" />

In this example, we'll create the `data-platform` org.

Next deploy a provisioner and template for this organization.

### 2. Deploy a provisioner

[Provisioners](../../install/operate/provisioners/index.md) are organization-scoped and are responsible
for executing Terraform/OpenTofu to provision the infrastructure for workspaces
and testing templates. Before creating templates, we must deploy at least one
provisioner as the built-in provisioners are scoped to the default organization.

1. Using Coder CLI, run the following command to create a key that will be used
   to authenticate the provisioner:

   ```sh
   coder provisioner keys create data-cluster-key --org data-platform
   Successfully created provisioner key data-cluster! Save this authentication token, it will not be shown again.

   < key omitted >
   ```

1. Start the provisioner with the key on your desired platform.

   In this example, start the provisioner using the Coder CLI on a host with
   Docker. For instructions on using other platforms like Kubernetes, see our
   [provisioner documentation](../../install/operate/provisioners/index.md).

   ```sh
   export CODER_URL=https://<your-coder-url>
   export CODER_PROVISIONER_DAEMON_KEY=<key>
   coder provisionerd start --org <org-name>
   ```

### 3. Create a template

Once you've started a provisioner, you can create a template. You'll notice the
**Create Template** screen now has an organization dropdown:

![Template Org Picker](../../images/admin/users/organizations/template-org-picker.png)

### 4. Add members

From **Admin settings**, select **Organizations**, then **Members** to add members to
your organization. Once added, members will be able to see the
organization-specific templates.

<img height="365px" src="../../images/admin/users/organizations/organization-members.png" alt="Add members" align="center" />

### 5. Create a workspace

Now, users in the data platform organization will see the templates related to
their organization. Users can be in multiple organizations.

![Workspace List](../../images/admin/users/organizations/workspace-list.png)

## Default member roles

> [!NOTE]
> Editing default member roles requires a Premium license.
> ([learn more](https://coder.com/pricing#compare-plans)).

Each organization carries a `default_org_member_roles` list of built-in role
names. Coder unions this list into every member's effective roles at request
time, so changes propagate to all current and future members on their next
request without re-issuing tokens or editing per-user role assignments.

The default value is `["organization-workspace-access", "agents-access"]`.
With that default, every organization member can read, build, ssh into, and
execute commands in workspaces they own, and can use Coder Agents. Removing
`organization-workspace-access` from the list creates organization members
that cannot create or use workspaces unless the role is assigned to them
directly, which is useful for restricted accounts that should only hold the
minimal member permissions. Removing `agents-access` limits Coder Agents to
members who hold the role directly. Refer to
[Control who can use Coder Agents](../../ai-coder/agents/getting-started.md#control-who-can-use-coder-agents).

Service accounts don't inherit `agents-access` from this list. Assign the
role to a service account directly to let it use Coder Agents.

To edit the default roles in the dashboard, go to
**Admin settings** > **Organizations** > **Roles** > **Default Roles**.

From the CLI, use `coder organizations edit`:

```shell
coder organizations edit --org <organization> \
  --default-org-member-roles organization-workspace-access,agents-access,organization-template-admin
```

The flag replaces the current list rather than adding to it, and accepts a
comma-separated list of built-in role names. Pass an empty value to remove
every role. Removing a role prompts for confirmation unless you pass
`--yes`.

You can also set `default_org_member_roles` via
`PATCH /organizations/{organization}`.

### Limitations

- `default_org_member_roles` accepts built-in role names only. Custom
  organization roles are rejected; assign them directly to members instead.
- Removing a role from the list removes it from every member that does not
  hold the role through a direct assignment, including existing members.
  Review the per-organization [audit log](../security/audit-logs.md) if you
  need to trace who changed the defaults.

## Next steps

- [Organizations - best practices](../../tutorials/best-practices/organizations.md)

---

# Quotas

Source: https://coder.com/docs/admin/users/quotas

Quotas are a mechanism for controlling spend by associating costs with workspace
templates and assigning budgets to users. Users that exceed their budget will be
blocked from launching more workspaces until they either delete their other
workspaces or get their budget extended.

For example: A template is configured with a cost of 5 credits per day, and the
user is granted 15 credits, which can be consumed by both started and stopped
workspaces. This budget limits the user to 3 concurrent workspaces.

Quotas are scoped to [Groups](./groups-roles.md) in Enterprise and
[organizations](./organizations.md) in Premium.

## Definitions

- **Credits** is the fundamental unit representing cost in the quota system.
  This integer can be arbitrary, or it can map to your preferred currency.
- **Budget** is the per-user, enforced, upper limit to credit spend.
- **Allowance** is a grant of credits to the budget.

<a id="establishing-costs"></a>

## Establish costs

Templates describe their cost through the `daily_cost` attribute in
[`resource_metadata`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/metadata).
Since costs are associated with resources, an offline workspace may consume less
quota than an online workspace.

A common use case is separating costs for a persistent volume and ephemeral
compute:

```tf
resource "docker_volume" "home_volume" {
  name = "coder-${data.coder_workspace_owner.me.name}-${data.coder_workspace.me.name}-root"
}

resource "coder_metadata" "home_volume" {
    resource_id = docker_volume.home_volume.id
    daily_cost  = 10
}

resource "docker_container" "workspace" {
  count = data.coder_workspace.me.start_count
  image = "codercom/code-server:latest"
  ...
  volumes {
    container_path = "/home/coder/"
    volume_name    = docker_volume.home_volume.name
    read_only      = false
  }
}

resource "coder_metadata" "workspace" {
    count       = data.coder_workspace.me.start_count
    resource_id = docker_container.workspace.id
    daily_cost  = 20
}
```

When the workspace above is shut down, the `docker_container` and
`coder_metadata` both get deleted. This reduces the cost from 30 credits to 10
credits.

Resources without a `daily_cost` value are considered to cost 0. If the cost was
removed on the `docker_volume` above, the template would consume 0 credits when
it's offline. This technique is good for incentivizing users to shut down their
unused workspaces and freeing up compute in the cluster.

<a id="establishing-budgets"></a>

## Establish budgets

Each group has a configurable Quota Allowance. A user's budget is calculated as
the sum of their allowances.

![group-settings](../../images/admin/users/quotas/quota-groups.png)

For example:

| Group Name | Quota Allowance |
|------------|-----------------|
| Frontend   | 10              |
| Backend    | 20              |
| Data       | 30              |

<br/>

| Username | Groups            | Effective Budget |
|----------|-------------------|------------------|
| jill     | Frontend, Backend | 30               |
| jack     | Backend, Data     | 50               |
| sam      | Data              | 30               |
| alex     | Frontend          | 10               |

By default, groups are assumed to have a default allowance of 0.

## Quota Enforcement

Coder enforces Quota on workspace start and stop operations. The workspace build
process dynamically calculates costs, so quota violation fails builds as opposed
to failing the build-triggering operation. For example, the Workspace Create
Form will never get held up by quota enforcement.

![build-log](../../images/admin/quota-buildlog.png)

## Up next

- [Group Sync](./idp-sync.md)
- [Control plane configuration](../setup/index.md)

---

# API & session tokens

Source: https://coder.com/docs/admin/users/sessions-tokens

Users can generate tokens to make API requests on behalf of themselves.

## Short-Lived Tokens (Sessions)

The [Coder CLI](../../install/cli.md) and
[Backstage Plugin](https://github.com/coder/backstage-plugins) use short-lived
token to authenticate. To generate a short-lived session token on behalf of your
account, visit the following URL: `https://coder.example.com/cli-auth`

### Retrieve the current session token

If you're already logged in with the CLI, you can retrieve your current session
token for use in scripts and automation:

```sh
coder login token
```

This is useful for passing your session token to other tools:

```sh
export CODER_SESSION_TOKEN=$(coder login token)
```

### Session Durations

By default, sessions last 24&nbsp;hours and are automatically refreshed.
You can configure [`CODER_SESSION_DURATION`](../../reference/cli/server/index.md#--session-duration) to change the duration and [`CODER_DISABLE_SESSION_EXPIRY_REFRESH`](../../reference/cli/server/index.md#--disable-session-expiry-refresh) to configure this behavior.

## Long-Lived Tokens (API Tokens)

Users can create long lived tokens. We refer to these as "API tokens" in the
product.

### Generate a long-lived API token on behalf of yourself

Use a unique name for each token.

<div class="tabs">

#### UI

Visit your account settings in the top right of the dashboard or by navigating
to `https://coder.example.com/settings/account`

Navigate to the tokens page in the sidebar and create a new token:

![Create an API token](../../images/admin/users/create-token.png)

#### CLI

Use the following command:

```sh
coder tokens create --name=my-token --lifetime=720h
```

See the help docs for
[`coder tokens create`](../../reference/cli/tokens/create.md) for more info.

</div>

### Generate a long-lived API token on behalf of another user

You must have the `Owner` role to generate a token for another user.

As of Coder v2.17+, you can use the CLI or API to create long-lived tokens on
behalf of other users. Use the API for earlier versions of Coder.

<div class="tabs">

#### CLI

```sh
coder tokens create --name my-token --user <username>
```

See the full CLI reference for
[`coder tokens create`](../../reference/cli/tokens/create.md)

#### API

Use our API reference for more information on how to
[create token API key](../../reference/api/users.md#create-token-api-key)

</div>

### Set max token length

You can use the
[`CODER_MAX_TOKEN_LIFETIME`](../../reference/cli/server/index.md#--max-token-lifetime)
server flag to set the maximum duration for long-lived tokens in your
deployment.

### Remove or expire a token

You can remove a token using the CLI or the API. By default, `coder tokens remove`
expires the token, (soft-delete):

```console
coder tokens remove <name|id>
```

Expired tokens can no longer be used for authentication and are hidden from
token listings by default. To include expired tokens, use the
`--include-expired` flag:

```console
coder tokens list --include-expired
```

To hard-delete a token, use the `--delete` flag:

```console
coder tokens remove --delete <name|id>
```

Deleting the user that owns a token revokes every token that user holds at the same time.

## API Key Scopes

API key scopes allow you to limit the permissions of a token to specific operations. By default, tokens are created with the `coder:all` scope, granting full access to all actions the user can perform. For improved security, you can create tokens with limited scopes that restrict access to only the operations needed.

Scopes follow the format `resource:action`, where `resource` is the type of object (like `workspace`, `template`, or `user`) and `action` is the operation (like `read`, `create`, `update`, or `delete`). You can also use wildcards like `workspace:*` to grant all permissions for a specific resource type.

<a id="creating-tokens-with-scopes"></a>

### Create tokens with scopes

You can specify scopes when creating a token using the `--scope` flag:

```sh
# Create a token that can only read workspaces
coder tokens create --name "readonly-token" --scope "workspace:read"

# Create a token with multiple scopes
coder tokens create --name "limited-token" --scope "workspace:read" --scope "template:read"
```

Common scope examples include:

- `workspace:read` - View workspace information
- `workspace:*` - Full workspace access (create, read, update, delete)
- `template:read` - View template information
- `api_key:read` - View API keys (useful for automation)
- `coder:application_connect` - Connect to workspace applications

The
[`codersdk.APIKeyScope` schema](../../reference/api/schemas.md#codersdkapikeyscope)
lists every scope name Coder defines, but a token cannot request all of them.
Internal scopes such as `debug_info:read` are rejected with a `400` response, so
use the `resource:action` and `coder:` names described on this page.

The older names `all` and `application_connect` are still accepted for backward compatibility. Tokens created with them are stored and listed as `coder:all` and `coder:application_connect`.

### Allow lists (advanced)

For additional security, you can combine scopes with allow lists to restrict tokens to specific resources. Allow lists let you limit a token to only interact with particular workspaces, templates, or other resources by their UUID:

```sh
# Create a token limited to a specific workspace
coder tokens create --name "workspace-token" \
  --scope "workspace:read" \
  --allow "workspace:a1b2c3d4-5678-90ab-cdef-1234567890ab"
```

**Important:** Allow lists are exclusive - the token can **only** perform actions on resources explicitly listed. In the example above, the token can only read the specified workspace and cannot access any other resources (templates, organizations, other workspaces, etc.). To maintain access to other resources, you must explicitly add them to the allow list:

```sh
# Token that can read one workspace AND access templates and user info
coder tokens create --name "limited-token" \
  --scope "workspace:read" --scope "template:*" --scope "user:read" \
  --allow "workspace:a1b2c3d4-5678-90ab-cdef-1234567890ab" \
  --allow "template:*" \
  --allow "user:*" \
  ... etc
```

---

# Template

Source: https://coder.com/docs/admin/templates

Templates are written in
[Terraform](https://developer.hashicorp.com/terraform/intro) and define the
underlying infrastructure that all Coder workspaces run on.

The [template builder](./creating-templates.md#template-builder) is
the recommended way to create templates. It guides you through selecting base
infrastructure, adding modules, and configuring your template without writing
Terraform.

## Learn the concepts

While templates are written in standard Terraform, it's important to learn the Coder-specific concepts behind templates.
The best way to learn the concepts is by [creating a basic template from scratch](../../tutorials/template-from-scratch.md).
If you are unfamiliar with Terraform, see [HashiCorp's Tutorials](https://developer.hashicorp.com/terraform/tutorials) for common cloud providers.

## Create a template

The fastest way to get started is with the
[template builder](./creating-templates.md#template-builder), which
composes a working template from a base infrastructure template and optional
registry modules. Starter templates for popular platforms (AWS, Kubernetes,
Docker, and others) are available as base templates in the builder, or through
the [CLI](./creating-templates.md#cli).

<a id="extending-templates"></a>

## Extend templates

It's often necessary to extend the template to make it generally useful to end
users. Common modifications are:

- Your image(s) (e.g. a Docker image with languages and tools installed). Docs:
  [Image management](./managing-templates/image-management.md).
- Additional parameters (e.g. disk size, instance type, or region). Docs:
  [Template parameters](./extending-templates/parameters.md).
- Additional IDEs (e.g. JetBrains) or features (e.g. dotfiles, RDP). Docs:
  [Adding IDEs and features](./extending-templates/index.md).

Learn more about the various ways you can
[extend your templates](./extending-templates/index.md).

## Best Practices

We recommend starting with a universal template that can be used for basic
tasks. As your Coder deployment grows, you can create more templates to meet the
needs of different teams.

- [Image management](./managing-templates/image-management.md): Learn how to
  create and publish images for use within Coder workspaces & templates.
- [Dev Containers integration](../integrations/devcontainers/integration.md): Enable
  native dev containers support using `@devcontainers/cli` and Docker.
- [Envbuilder](../integrations/devcontainers/envbuilder/index.md): Alternative approach
  for environments without Docker access.
- [Template hardening](./extending-templates/resource-persistence.md#-bulletproofing):
  Configure your template to prevent certain resources from being destroyed
  (e.g. user disks).
- [Manage templates with Ci/Cd pipelines](./managing-templates/change-management.md):
  Learn how to source control your templates and use GitOps to ensure template
  changes are reviewed and tested.
- [Permissions and Policies](./template-permissions.md): Control who may access
  and modify your template.
- [External Workspaces](./managing-templates/external-workspaces.md): Learn how to connect your existing infrastructure to Coder workspaces.

<children></children>

---

# Creating Templates

Source: https://coder.com/docs/admin/templates/creating-templates

Users with the `Template Administrator` role or above can create templates
within Coder.

## From a starter template

In most cases, it is best to start with a starter template.

<div class="tabs">

### Template builder

The template builder is the recommended way to create templates in Coder. It
guides you through selecting a base infrastructure template, adding modules
(IDEs, tools, integrations), and configuring your template, all without writing
Terraform.

The template builder is enabled by default. When you select **New Template** on
the **Templates** page, the builder opens automatically.

The builder guides you through up to five steps:

1. **Select base infrastructure**: Choose a starter template for your target
   platform (e.g. Docker, AWS EC2, Kubernetes). Each base template provides a
   working foundation with the Coder agent pre-configured.

   ![Select a base infrastructure template in the template builder](../../images/templatebuilder_01_bases.png)

1. **Base template parameters** *(optional)*: If the selected base template
   declares configurable variables, you can supply values for them here.
   If the base template has no parameters, this step is skipped automatically.

1. **Select modules**: Pick from a curated list of
   [registry modules](https://registry.coder.com) to add IDEs, AI agents,
   source control integrations, and other tools. Modules are grouped by
   category and filtered for compatibility with the selected base template's
   operating system. You can select multiple modules.

   ![Select modules to add to your template](../../images/templatebuilder_02_modules.png)

1. **Module settings** *(optional)*: Configure variables for the modules you
   selected. Required variables without defaults must be filled in before you
   can proceed. Modules that require secrets (such as API keys) display a
   notice that developers will be prompted for the value at workspace creation
   time.

   ![Configure module settings](../../images/templatebuilder_03_module_customization.png)

1. **Template customizations**: Set the template's display name, description,
   icon, and organization, then select **Create Template**.

   ![Set template display name, description, and other metadata](../../images/templatebuilder_04_customizations.png)

After you select **Create Template**, Coder composes the Terraform
configuration server-side, validates it with `terraform init` and
`terraform validate`, and creates the template. The generated template is
standard Terraform HCL that you can edit later through the dashboard or CLI.

> [!NOTE]
> The template builder requires outbound access to `registry.coder.com` so
> that `terraform init` can resolve module sources. For air-gapped or
> restricted-egress deployments, visit
> [Air-gapped deployments](../../install/prepare/airgap.md#template-builder).

If you select modules that are known to conflict with each other, the builder
displays a warning. Module conflicts do not block template creation, but you
should review the warning before proceeding.

<a id="disabling-the-template-builder"></a>

#### Turn off the template builder

Operators can disable the template builder by setting the
`CODER_DISABLE_TEMPLATE_BUILDER` environment variable or the
`--disable-template-builder` server flag. When disabled, the **New Template**
button links to the starter templates page instead, and the
`/api/v2/templatebuilder/*` endpoints return 404.

Deployments using a self-hosted module registry mirror can set
`CODER_TEMPLATE_BUILDER_REGISTRY_URL` to point generated module source paths at
the mirror instead of `registry.coder.com`.
The value is a bare host, optionally with a port (for example `mirror.internal:8443`).
A leading `http(s)://` scheme and trailing slash are stripped, and a path, query, fragment, or credentials is rejected at server start.

#### Alternative creation methods

The template builder's first step also links to alternative creation paths:

- **Upload an existing template**: Upload a `.tar.gz` or `.zip` of Terraform
  files you have authored locally.
- **Start from scratch**: Follow the
  [template from scratch tutorial](../../tutorials/template-from-scratch.md) to
  write Terraform by hand.
- **Browse community templates**: Browse the
  [Coder Registry](https://registry.coder.com/templates) for community and
  official templates.

### CLI

You can use the [Coder CLI](../../install/cli.md) to manage templates for Coder.

After [logging in](../../reference/cli/login/index.md) to your deployment, create a
folder to store your templates:

```sh
# This snippet applies to macOS and Linux only
mkdir $HOME/coder-templates
cd $HOME/coder-templates
```

Use the [`templates init`](../../reference/cli/templates/init.md) command to
pull a starter template:

```sh
coder templates init
```

After pulling the template to your local machine (e.g. `aws-linux`), you can
rename it:

```sh
# This snippet applies to macOS and Linux only
mv aws-linux universal-template
cd universal-template
```

Next, push it to Coder with the
[`templates push`](../../reference/cli/templates/push.md) command:

```sh
coder templates push
```

If `templates push` fails, it is likely that Coder is not authorized to deploy
infrastructure in the given location. Learn how to configure
[provisioner authentication](../../install/operate/provisioners/index.md).

You can edit the metadata of the template such as the display name with the
[`templates edit`](../../reference/cli/templates/edit.md) command:

```sh
coder templates edit universal-template \
  --display-name "Universal Template" \
  --description "Virtual machine configured with Java, Python, Typescript, IntelliJ IDEA, and Ruby. Use this for starter projects. " \
  --icon "/emojis/2b50.png"
```

### CI/CD

Follow the [change management](./managing-templates/change-management.md) guide
to manage templates via GitOps.

</div>

## From an existing template

You can duplicate an existing template in your Coder deployment. This copies
the template code and metadata, allowing you to make changes without affecting
the original template.

<div class="tabs">

### Web UI

After navigating to the page for a template, use the dropdown menu on the right
to `Duplicate`.

![Duplicate menu](../../images/admin/templates/duplicate-menu.png)

Give the new template a name, icon, and description.

![Duplicate page](../../images/admin/templates/duplicate-page.png)

Press `Create template`. After the build, you will be taken to the new template
page.

![New template](../../images/admin/templates/new-duplicate-template.png)

### CLI

First, ensure you are logged in to the control plane as a user with permissions
to read and write permissions.

```console
coder login
```

You can list the available templates with the following CLI invocation.

```console
coder templates list
```

After identified the template you'd like to work from, clone it into a directory
with a name you'd like to assign to the new modified template.

```console
coder templates pull <template-name> ./<new-template-name>
```

Then, you can make modifications to the existing template in this directory and
push them to the control plane using the `-d` flag to specify the directory.

```console
coder templates push <new-template-name> -d ./<new-template-name>
```

You will then see your new template in the dashboard.

</div>

## From scratch (advanced)

There may be cases where you want to create a template from scratch. You can use
[any Terraform provider](https://registry.terraform.io) with Coder to create
templates for additional clouds (e.g. Hetzner, Alibaba) or orchestrators
(VMware, Proxmox) that we do not provide example templates for.

Refer to the following resources:

- [Tutorial: Create a template from scratch](../../tutorials/template-from-scratch.md)
- [Extending templates](./extending-templates/index.md): Features and concepts
  around templates (agents, parameters, variables, etc)
- [Coder Registry](https://registry.coder.com/templates): Official and community
  templates for Coder
- [Coder Terraform Provider Reference](https://registry.terraform.io/providers/coder/coder)

### Next steps

- [Extending templates](./extending-templates/index.md)
- [Managing templates](./managing-templates/index.md)

---

# Work with templates

Source: https://coder.com/docs/admin/templates/managing-templates

You create and edit Coder templates as
[Terraform](https://developer.hashicorp.com/terraform/intro) configuration files
(`.tf`) and any supporting files, like a README or configuration files for other
services.

## Who creates templates?

The [Template Admin](../../../admin/users/groups-roles.md#roles) role (and
above) can create templates. End users, like developers, create workspaces from
them. Templates can also be [managed with git](./change-management.md), allowing
any developer to propose changes to a template.

You can give different users and groups access to templates with
[role-based access control](../template-permissions.md).

<a id="creating-templates"></a>

## Create templates

The [template builder](../creating-templates.md#template-builder) is the
recommended way to create templates. It guides you through selecting a base
infrastructure template, adding modules (IDEs, tools, integrations), and
configuring template settings without writing Terraform.

Starter templates for common cloud providers (AWS, Azure) and orchestrators
(Kubernetes, Docker) are available as base templates within the builder. You can
modify the generated template to use your own images, VPC, cloud credentials,
and so on. Coder supports all Terraform resources and properties.

If you prefer to use Coder on the
[command line](../../../reference/cli/index.md), use `coder templates init` to
pull a starter template, then `coder templates push` to upload it.

Coder starter templates are also available on our
[GitHub repo](../../../../examples/templates).

## Community Templates

As well as Coder's starter templates, you can see a list of community templates
by our users [here](../../../../examples/templates/community-templates.md).

<a id="editing-templates"></a>

## Edit templates

Our templates are meant to be modified for your use cases. You can edit any
template's files directly in the Coder dashboard.

![Editing a template](../../../images/templates/choosing-edit-template.gif)

If you'd prefer to use the CLI, use `coder templates pull`, edit the template
files, then `coder templates push`.

> [!TIP]
> Even if you are a Terraform expert, we suggest reading our
> [guided tour of a template](../../../tutorials/template-from-scratch.md).

<a id="updating-templates"></a>

## Update templates

Coder tracks a template's versions, keeping all developer workspaces up-to-date.
When you publish a new version, developers are notified to get the latest
infrastructure, software, or security patches. Learn more about
[change management](./change-management.md).

![Updating a template](../../../images/templates/update.png)

### Template update policies

> [!NOTE]
> Template update policies are a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Licensed template admins may want workspaces to always remain on the latest
version of their parent template. To do so, enable **Template Update Policies**
in the template's general settings. All non-admin users of the template will be
forced to update their workspaces before starting them once the setting is
applied. Workspaces which leverage autostart or start-on-connect will be
automatically updated on the next startup.

![Template update policies](../../../images/templates/update-policies.png)

## Refresh template data

Coder reads Terraform `data` sources once, when it imports a template version.
Every workspace built from that version reuses those stored results.

Refreshing imports the active version's source files again and publishes the
result as the new active version. Use it to pick up changes to a `data` source,
or to give an older version the metadata that
[Dynamic Parameters](../extending-templates/dynamic-parameters.md) needs.

To refresh a template's data:

1. Navigate to the template, then select **Settings** > **Parameters**.
1. Select **Refresh template data**, then confirm.

The **Template data** section on that page shows which version is active and
when Coder last imported it.

New workspaces use the refreshed version as soon as the import finishes.
Workspaces that are already running stay on their current version until you
update them.

Refreshing a template's data requires permission to update the template, which
the [Template Admin](../../users/groups-roles.md#roles) role and above have.

## Workspace renaming

Workspace renaming is disabled by default on every template. Enable it per
template, once you have confirmed that a rename won't destroy anything.

Terraform exposes the workspace name as `data.coder_workspace.me.name`. If a
template uses that value in an attribute Terraform can't change in place,
renaming the workspace makes Terraform destroy the resource and create a new one
on the next build. When that resource is the home volume, the developer loses
their data.

Other uses of the name are harmless. A Kubernetes label or an environment
variable changes without replacing anything. Coder can't tell the two cases
apart, so the decision stays with the template admin.

### Check whether your template is safe to rename

Search the template for uses of the workspace name:

```sh
grep -rn 'coder_workspace\.[a-z_]*\.name' .
```

For each result, ask whether Terraform would replace the resource if that value
changed. Attributes such as a volume name, a disk name, or an instance name
usually force replacement. Labels, tags, and environment variables usually
don't.

If a resource would be replaced, reference an immutable identifier instead, such
as `data.coder_workspace.me.id`. Refer to
[Resource persistence](../extending-templates/resource-persistence.md) for the
full set of practices.

### Enable renaming for a template

1. Go to the template, then select **Settings**.
1. On the **General** page, under **Operations**, select **Allow users to rename
   their workspaces**.
1. Select **Save**.

Developers can then rename a workspace from the workspace's **Settings** page,
or with `coder rename`.

While the setting is off, the workspace name field is disabled and the API
rejects renames.

> [!WARNING]
> The deployment-wide `CODER_ALLOW_WORKSPACE_RENAMES` option is deprecated.
> While it is set, renaming is enabled for every template in the deployment,
> and the per-template setting can't turn it off. Unset it, then enable
> renaming on the templates that need it.

## Delete templates

You can delete a template using both the coder CLI and UI. Only
[template admins and owners](../../users/groups-roles.md#roles) can delete a
template, and the template must not have any running workspaces associated to
it.

In the UI, navigate to the template you want to delete, and select the dropdown
in the right-hand corner of the page to delete the template.

![delete-template](../../../images/delete-template.png)

Using the CLI, login to Coder and run the following command to delete a
template:

```sh
coder templates delete <template-name>
```

## Next steps

- [Image management](./image-management.md)
- [Dev Containers integration](../../integrations/devcontainers/integration.md)
  (recommended)
- [Envbuilder](../../integrations/devcontainers/envbuilder/index.md)
  (alternative for environments without Docker)
- [Change management](./change-management.md)

---

# Image Management

Source: https://coder.com/docs/admin/templates/managing-templates/image-management

While Coder provides example
[container images](https://github.com/coder/images) for
workspaces, it's often best to create custom images that match the needs of
your users. This document serves as a guide to operational maturity with some
best practices around managing workspace images for Coder.

After following this tutorial, you'll accomplish the following:

1. Create a minimal base image.
2. Create golden images with standard tooling.
3. Create project-specific images for common use cases.
4. Let developers customize their own environment.

An image is just one of the many properties defined within the template.
Templates can pull images from a public image registry (e.g. Docker Hub) or an
internal one, thanks to Terraform. Each image reference below can be dropped
directly into a template's image variable or parameter.

## Create a minimal base image

While you may not use this directly in Coder templates, it's useful to have a
minimal base image as a small image that contains only the necessary
dependencies to work in your network and work with Coder. Here are some things
to consider:

- `curl`, `wget`, or `busybox` is required to download and run
  [the agent](../../../../provisionersdk/scripts/bootstrap_linux.sh)
- `git` is recommended so developers can clone repositories
- If the control plane is using a certificate from an internal certificate
  authority (CA), you'll need to add or mount these into your image
- Other generic utilities that will be required by all users, such as `ssh`,
  `docker`, `bash`, `jq`, and/or internal tooling
- Consider creating (and starting the container with) a non-root user

Examples:

- [`codercom/example-minimal:ubuntu`](https://github.com/coder/images/tree/main/images/minimal): only the necessary dependencies for a Coder workspace to bootstrap
- [`codercom/example-base:ubuntu`](https://github.com/coder/images/tree/main/images/base): a slightly more padded starting point with common utilities preinstalled

## Create golden images with standard tooling

Building on the base image, it's often practical to have a few golden images
that contain standard tooling for developers. These images should contain a
number of languages (e.g. Python, Java, TypeScript), IDEs (VS Code, JetBrains,
PyCharm), and other tools (e.g. `docker`). Unlike project-specific images
(which are also important), general purpose images are great for:

- **Scripting:** Developers may just want to hop in a Coder workspace to run
  basic scripts or queries.
- **Day 1 Onboarding:** New developers can quickly get started with a familiar
  environment without having to browse through (or create) an image
- **Basic Projects:** Developers can use these images for simple projects that
  don't require any specific tooling outside of the standard libraries. As the
  project gets more complex, its best to move to a project-specific image.
- **"Golden Path" Projects:** If your developer platform offers specific tech
  stacks and types of projects, the golden image can be a good starting point
  for those projects.

This is often referred to as a "sandbox" or "kitchen sink" image. Since large
multi-purpose container images can quickly become difficult to maintain, it's
important to keep the number of general-purpose images to a minimum (2-3 in
most cases) with a well-defined scope.

Examples:

- [`codercom/example-universal:ubuntu`](https://github.com/coder/images/tree/main/images/universal): a catch-all image with many languages and tools preinstalled. Runs as the `coder` user, so it works with Coder templates out of the box.
- [`mcr.microsoft.com/devcontainers/universal`](https://github.com/devcontainers/images/tree/main/src/universal): the Universal Dev Containers image

## Create project-specific images for common use cases

Beyond golden images, create images scoped to a specific project, language, or
use case (e.g., a Go backend, a Node.js frontend, or a data science stack).
These images stay smaller and faster to pull than one larger image that tries to install all dependencies.

Examples:

- [`codercom/example-golang:ubuntu`](https://github.com/coder/images/tree/main/images/golang),
  [`codercom/example-java:ubuntu`](https://github.com/coder/images/tree/main/images/java),
  [`codercom/example-node:ubuntu`](https://github.com/coder/images/tree/main/images/node):
  Coder's example language-specific images, all running as the `coder` user.
  Refer to [coder/images](https://github.com/coder/images) for the full list.
- [`codercom/oss-dogfood:latest`](https://github.com/coder/coder/tree/main/dogfood):
  the image Coder's own engineers use to develop Coder. A good reference for a
  project-specific image tailored to a specific team or monorepo setup.

## Let developers customize their own environment

Even with well-scoped images, developers will often need tooling that is
specific to their project or personal workflow. Instead of maintaining an
image for every combination, developers can layer their own customizations
on top of a smaller image:

- [Dev Containers](https://containers.dev): developers define their project's
  dependencies in a `devcontainer.json` in their Git repository, and Coder
  builds the environment on top of your base image. Visit
  [configure a template for Dev Containers](../../integrations/devcontainers/integration.md).
- [mise](https://mise.jdx.dev/): developers install and pin language runtimes
  and CLI tools at workspace startup without rebuilding the image. Visit the
  [install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md).

---

# Template change management

Source: https://coder.com/docs/admin/templates/managing-templates/change-management

We recommend source-controlling your templates as you would other any code, and
automating the creation of new versions in CI/CD pipelines.

These pipelines will require tokens for your deployment. To cap token lifetime
on creation,
[configure the control plane to set a shorter max token lifetime](../../../reference/cli/server/index.md#--max-token-lifetime).

## coderd Terraform Provider

The
[coderd Terraform provider](https://registry.terraform.io/providers/coder/coderd/latest)
can be used to push new template versions, either manually, or in CI/CD
pipelines. To run the provider in a CI/CD pipeline, and to prevent drift, you'll
need to store the Terraform state
[remotely](https://developer.hashicorp.com/terraform/language/backend).

```tf
terraform {
  required_providers {
    coderd = {
      source = "coder/coderd"
    }
  }
  backend "gcs" {
    bucket = "example-bucket"
    prefix = "terraform/state"
  }
}

provider "coderd" {
  // Can be populated from environment variables
  url   = "https://coder.example.com"
  token = "****"
}

// Get the commit SHA of the configuration's git repository
variable "TFC_CONFIGURATION_VERSION_GIT_COMMIT_SHA" {
  type = string
}

resource "coderd_template" "kubernetes" {
  name = "kubernetes"
  description = "Develop in Kubernetes!"
  versions = [{
    directory = ".coder/templates/kubernetes"
    active    = true
    # Version name is optional
    name = var.TFC_CONFIGURATION_VERSION_GIT_COMMIT_SHA
    tf_vars = [{
      name  = "namespace"
      value = "default4"
    }]
  }]
  /* ... Additional template configuration */
}
```

For an example, see how we push our development image
[with GitHub actions](../../../../.github/workflows/dogfood.yaml).

## Coder CLI

You can [install Coder](../../../install/cli.md) CLI to automate pushing new
template versions in CI/CD pipelines. For GitHub Actions, see our
[setup-coder](https://github.com/coder/setup-coder) action.

```console
# Install the Coder CLI
curl -fsSL https://coder.com/install.sh | sh
# curl -fsSL https://coder.com/install.sh | sh -s -- --version=0.x

# To create API tokens, use `coder tokens create`.
# If no `--lifetime` flag is passed during creation, the default token lifetime
# will be 30 days.
# These variables are consumed by Coder
export CODER_URL=https://coder.example.com
export CODER_SESSION_TOKEN=*****

# Template details
export CODER_TEMPLATE_NAME=kubernetes
export CODER_TEMPLATE_DIR=.coder/templates/kubernetes
export CODER_TEMPLATE_VERSION=$(git rev-parse --short HEAD)

# Push the new template version to Coder
coder templates push --yes $CODER_TEMPLATE_NAME \
    --directory $CODER_TEMPLATE_DIR \
    --name=$CODER_TEMPLATE_VERSION # Version name is optional
```

<a id="testing-and-publishing-coder-templates-in-cicd"></a>

## Test and publish Coder templates in CI/CD

See our [testing templates](../../../tutorials/testing-templates.md) tutorial
for an example of how to test and publish Coder templates in a CI/CD pipeline.

### Next steps

- [Coder CLI Reference](../../../reference/cli/templates/index.md)
- [Coderd Terraform Provider Reference](https://registry.terraform.io/providers/coder/coderd/latest/docs)
- [Coderd API Reference](../../../reference/index.md)

---

# Envbuilder

Source: https://coder.com/docs/admin/templates/managing-templates/envbuilder

Envbuilder shifts environment definition from template administrators to
developers. Instead of baking tools into template images, developers define
their environments via `devcontainer.json` files in their repositories.

Envbuilder transforms the workspace image itself from a dev container
configuration, without requiring a Docker daemon.

For setup instructions, see
[Envbuilder documentation](../../integrations/devcontainers/envbuilder/index.md).

For an alternative that uses Docker inside workspaces, see
[Dev Containers Integration](../../integrations/devcontainers/integration.md).

---

# Template Dependencies

Source: https://coder.com/docs/admin/templates/managing-templates/dependencies

When creating Coder templates, it is unlikely that you will just be using
built-in providers. Part of Terraform's flexibility stems from its rich plugin
ecosystem, and it makes sense to take advantage of this.

That having been said, here are some recommendations to follow, based on the
[Terraform documentation](https://developer.hashicorp.com/terraform/tutorials/configuration-language/provider-versioning).

Following these recommendations will:

- **Prevent unexpected changes:** Your templates will use the same versions of
  Terraform providers each build. This will prevent issues related to changes in
  providers.
- **Improve build performance:** Coder caches provider versions on each build.
  If the same provider version can be re-used on subsequent builds, Coder will
  simply re-use the cached version if it is available.
- **Improve build reliability:** As some providers are hundreds of megabytes in
  size, interruptions in connectivity to the Terraform registry during a
  workspace build can result in a failed build. If Coder is able to re-use a
  cached provider version, the likelihood of this is greatly reduced.

## Lock your provider and module versions

If you add a Terraform provider to `required_providers` without specifying a
version requirement, Terraform will always fetch the latest version on each
invocation:

```tf
terraform {
  required_providers {
    coder = {
      source = "coder/coder"
    }
    frobnicate = {
      source = "acme/frobnicate"
    }
  }
}
```

Any new releases of the `coder` or `frobnicate` providers will be picked up upon
the next time a workspace is built using this template. This may include
breaking changes.

To prevent this, add a
[version constraint](https://developer.hashicorp.com/terraform/language/expressions/version-constraints)
to each provider in the `required_providers` block:

```tf
terraform {
  required_providers {
    coder = {
      source = "coder/coder"
      version = ">= 0.2, < 0.3"
    }
    frobnicate = {
      source = "acme/frobnicate"
      version = "~> 1.0.0"
    }
  }
}
```

In the above example, the `coder/coder` provider will be limited to all versions
above or equal to `0.2.0` and below `0.3.0`, while the `acme/frobnicate`
provider will be limited to all versions matching `1.0.x`.

The above also applies to Terraform modules. In the below example, the module
`razzledazzle` is locked to version `1.2.3`.

```tf
module "razzledazzle" {
  source  = "registry.example.com/modules/razzle/dazzle"
  version = "1.2.3"
  foo     = "bar"
}
```

## Use a Dependency Lock File

Terraform allows creating a
[dependency lock file](https://developer.hashicorp.com/terraform/language/files/dependency-lock)
to track which provider versions were selected previously. This allows you to
ensure that the next workspace build uses the same provider versions as with the
last build.

To create a new Terraform lock file, run the
[`terraform init` command](https://developer.hashicorp.com/terraform/cli/commands/init)
inside a folder containing the Terraform source code for a given template.

This will create a new file named `.terraform.lock.hcl` in the current
directory. When you next run
[`coder templates push`](../../../reference/cli/templates/push.md), the lock
file will be stored alongside with the other template source code.

> [!NOTE]
> Terraform best practices also recommend checking in your
> `.terraform.lock.hcl` into Git or other VCS.

The next time a workspace is built from that template, Coder will make sure to
use the same versions of those providers as specified in the lock file.

If, at some point in future, you need to update the providers and versions you
specified within the version constraints of the template, run

```console
terraform init -upgrade
```

This will check each provider, check the newest satisfiable version based on the
version constraints you specified, and update the `.terraform.lock.hcl` with
those new versions. When you next run `coder templates push`, again, the updated
lock file will be stored and used to determine the provider versions to use for
subsequent workspace builds.

---

# Workspace Scheduling

Source: https://coder.com/docs/admin/templates/managing-templates/schedule

You can configure a template to control how workspaces are started and stopped.
You can also manage the lifecycle of failed or inactive workspaces.

![Schedule screen](../../../images/admin/templates/schedule/template-schedule-settings.png)

## Schedule

Template [admins](../../users/index.md) may define these default values:

- [**Default autostop**](../../../user-guides/workspace-scheduling.md#autostop):
  How long a workspace runs without user activity before Coder automatically
  stops it.
- [**Autostop requirement**](#autostop-requirement): Enforce mandatory workspace
  restarts to apply template updates regardless of user activity.
- **Activity bump**: The duration by which to extend a workspace's deadline when activity is detected (default: 1&nbsp;hour). The workspace will be considered inactive when no sessions are detected (VSCode, JetBrains, Terminal, or SSH). For details on what counts as activity, see the [user guide on activity detection](../../../user-guides/workspace-scheduling.md#activity-detection).
- **Dormancy**: This allows automatic deletion of unused workspaces to reduce
  spend on idle resources.

## Allow users scheduling

For templates where a uniform autostop duration is not appropriate, admins may
allow users to define their own autostart and autostop schedules. Admins can
restrict the days of the week a workspace should automatically start to help
manage infrastructure costs.

## Failure cleanup

> [!NOTE]
> Failure cleanup is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Failure cleanup defines how long a workspace is permitted to remain in the
failed state prior to being automatically stopped. Failure cleanup is only
available for licensed customers.

## Dormancy threshold

> [!NOTE]
> Dormancy threshold is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Dormancy Threshold defines how long Coder allows a workspace to remain inactive
before being moved into a dormant state. A workspace's inactivity is determined
by the time elapsed since a user last accessed the workspace. A workspace in the
dormant state is not eligible for autostart and must be manually activated by
the user before being accessible. Coder stops workspaces during their transition
to the dormant state if they are detected to be running. Dormancy Threshold is
only available for licensed customers.

## Dormancy auto-deletion

> [!NOTE]
> Dormancy auto-deletion is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Dormancy Auto-Deletion allows a template admin to dictate how long a workspace
is permitted to remain dormant before it is automatically deleted. Dormancy
Auto-Deletion is only available for licensed customers.

## Autostop requirement

> [!NOTE]
> Autostop requirement is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Autostop requirement is a template setting that determines how often workspaces
using the template must automatically stop. Autostop requirement ignores any
active connections, and ensures that workspaces do not run in perpetuity when
connections are left open inadvertently.

Workspaces will apply the template autostop requirement on the given day in the
user's timezone and specified quiet hours (see below). This ensures that
workspaces will not be stopped during work hours.

The available options are "Days", which can be set to "Daily", "Saturday" or
"Sunday", and "Weeks", which can be set to any number from 1 to 16.

"Days" governs which days of the week workspaces must stop. If you select
"daily", workspaces must be automatically stopped every day at the start of the
user's defined quiet hours. When using "Saturday" or "Sunday", workspaces will
be automatically stopped on Saturday or Sunday in the user's timezone and quiet
hours.

"Weeks" determines how many weeks between required stops. It cannot be changed
from the default of 1 if you have selected "Daily" for "Days". When using a
value greater than 1, workspaces will be automatically stopped every N weeks on
the day specified by "Days" and the user's quiet hours. The autostop week is
synchronized for all workspaces on the same template.

Autostop requirement is disabled when the template is using the deprecated max
lifetime feature. Templates can choose to use a max lifetime or an autostop
requirement during the deprecation period, but only one can be used at a time.

## User quiet hours

> [!NOTE]
> User quiet hours are a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

User quiet hours can be configured in the user's schedule settings page.
Workspaces on templates with an autostop requirement will only be forcibly
stopped due to the policy at the start of the user's quiet hours.

![User schedule settings](../../../images/admin/templates/schedule/user-quiet-hours.png)

Admins can define the default quiet hours for all users with the
[CODER_QUIET_HOURS_DEFAULT_SCHEDULE](../../../reference/cli/server/index.md#--default-quiet-hours-schedule)
environment variable. The value should be a cron expression such as
`CRON_TZ=America/Chicago 30 2 * * *` which would set the default quiet hours to
2:30 AM in the America/Chicago timezone. The cron schedule can only have a
minute and hour component. The default schedule is UTC 00:00. It is recommended
to set the default quiet hours to a time when most users are not expected to be
using Coder.

Admins can force users to use the default quiet hours with the
[CODER_ALLOW_CUSTOM_QUIET_HOURS](../../../reference/cli/server/index.md#--allow-custom-quiet-hours)
environment variable. Users will still be able to see the page, but will be
unable to set a custom time or timezone. If users have already set a custom
quiet hours schedule, it will be ignored and the default will be used instead.

---

# External Workspaces

Source: https://coder.com/docs/admin/templates/managing-templates/external-workspaces

External workspaces allow you to seamlessly connect externally managed infrastructure as Coder workspaces. This enables you to integrate existing servers, on-premises systems, or any capable machine with the Coder environment, ensuring a smooth and efficient development workflow without requiring Coder to provision additional compute resources.

## Prerequisites

- Access to external compute resources that can run the Coder agent:
  - **Windows**: amd64 or arm64 architecture
  - **Linux**: amd64, arm64, or armv7 architecture
  - **macOS**: amd64 or arm64 architecture
  - **Examples**: VMs, bare-metal servers, Kubernetes nodes, or any machine meeting the above requirements.
- Networking access to your Coder deployment.
- A workspace template that includes a [`coder_external_agent`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/external_agent) resource.

We provide an example template on how to set up external workspaces in the [Coder Registry](https://registry.coder.com/templates/coder-labs/externally-managed-workspace)

## Benefits

External workspaces offer flexibility and control in complex environments:

- **Incremental adoption of Coder**

  Integrate with existing infrastructure gradually without needing to migrate everything at once. This is particularly useful when gradually migrating workloads to Coder without refactoring current infrastructure.

- **Flexibility**

  Attach cloud, hybrid, or on-premises machines as developer workspaces. This enables connecting existing on-premises GPU servers for ML development or bringing manually provisioned VMs in restricted networks under Coder's workspace management.

- **Separation of concerns**

  Provision compute resources externally (using your existing IaC or manual processes) while managing workspace configuration (apps, scripts) with Terraform. This approach is ideal for running agents in CI pipelines to provision short-lived, externally managed workspaces for testing or build automation.

## Known limitations

- **Lifecycle control**

  Start/stop/restart actions in the Coder UI are disabled for external workspaces.
- **No automatic deprovisioning**

  Deleting an external workspace in Coder removes the agent token and record, but does not delete the underlying compute resource.
- **Manual agent management**

  Administrators are responsible for deploying and maintaining agents on external resources.
- **Limited UI indicators**

  External workspaces are marked in the UI, but underlying infrastructure health is not monitored by Coder.

## When to use it?

Use external workspaces if:

- You have compute resources provisioned outside of Coder’s Terraform flows.
- You want to connect specialized or legacy systems to your Coder deployment.
- You are migrating incrementally to Coder and need hybrid support.
- You need finer control over how and where agents run, while still benefiting from Coder’s workspace experience.

## How to use it?

You can create and manage external workspaces using either the **CLI** or the **UI**.

<div class="tabs">

### CLI

1. **Create an external workspace**

   ```sh
   coder external-workspaces create hello-world \
     --template=externally-managed-workspace -y
   ```

   - Validates that the template includes a `coder_external_agent` resource.
   - Once created, the workspace is registered in Coder but marked as requiring an external agent.

2. **List external workspaces**

   ```sh
   coder external-workspaces list
   ```

   Example output:

   ```sh
   WORKSPACE        TEMPLATE                     STATUS   HEALTHY  LAST BUILT  CURRENT VERSION  OUTDATED
   hello-world      externally-managed-workspace Started  true     15m         happy_mendel9    false
   ```

3. **Retrieve agent connection instructions**

   Use this command to query the script you must run on the external machine:

   ```sh
   coder external-workspaces agent-instructions hello-world
   ```

   Example:

   ```sh
   Please run the following command to attach external agent to the workspace hello-world:

   curl -fsSL "https://<DEPLOYMENT_URL>/api/v2/init-script/linux/amd64" | CODER_AGENT_TOKEN="<token>" sh
   ```

   You can also output JSON for automation:

   ```sh
   coder external-workspaces agent-instructions hello-world --output=json
   ```

   ```json
   {
     "workspace_name": "hello-world",
     "agent_name": "main",
     "auth_type": "token",
     "auth_token": "<token>",
     "init_script": "curl -fsSL \"https://<DEPLOYMENT_URL>/api/v2/init-script/linux/arm64\" | CODER_AGENT_TOKEN=\"<token>\" sh"
   }
   ```

### UI

1. Import the external workspace template (see prerequisites).
2. In the Coder UI, go to **Workspaces → New workspace** and select the imported template.
3. Once the workspace is created, Coder will display **connection details** with the command users need to run on the external machine to start the agent.
4. The workspace will appear in the dashboard, but with the following differences:
   - **Start**, **Stop**, and **Restart** actions are disabled.
   - Users are provided with instructions for launching the agent manually on the external machine.

![External Workspace View](../../../images/admin/templates/external-workspace.png)

</div>

---

# Extend templates

Source: https://coder.com/docs/admin/templates/extending-templates

There are a variety of Coder-native features to extend the configuration of your
development environments. Many of the following features are defined in your
templates using the
[Coder Terraform provider](https://registry.terraform.io/providers/coder/coder/latest/docs).
The provider docs will provide code examples for usage; alternatively, you can
view our
[example templates](../../../../examples/templates)
to get started.

## Workspace agents

For users to connect to a workspace, the template must include a
[`coder_agent`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent).
The associated agent will facilitate
[workspace connections](../../../user-guides/workspace-access/index.md) via SSH,
port forwarding, and IDEs. The agent may also display real-time
[workspace metadata](./agent-metadata.md) like resource usage.

```tf
resource "coder_agent" "dev" {
  os   = "linux"
  arch = "amd64"
  dir  = "/workspace"
  display_apps {
    vscode = true
  }
}
```

You can also leverage [resource metadata](./resource-metadata.md) to display
static resource information from your template.

Templates must include some computational resource to start the agent. All
processes on the workspace are then spawned from the agent. It also provides all
information displayed in the dashboard's workspace view.

![A healthy workspace agent](../../../images/templates/healthy-workspace-agent.png)

Multiple agents may be used in a single template or even a single resource. Each
agent may have its own apps, startup script, and metadata. This can be used to
associate multiple containers or VMs with a workspace.

## Resource persistence

The resources you define in a template may be _ephemeral_ or _persistent_.
Persistent resources stay provisioned when workspaces are stopped, where as
ephemeral resources are destroyed and recreated on restart. All resources are
destroyed when a workspace is deleted.

You can read more about how resource behavior and workspace state in the [workspace lifecycle documentation](../../../user-guides/workspace-lifecycle.md).

Template resources follow the
[behavior of Terraform resources](https://developer.hashicorp.com/terraform/language/resources/behavior#how-terraform-applies-a-configuration)
and can be further configured  using the
[lifecycle argument](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle).

A common configuration is a template whose only persistent resource is the home
directory. This allows the developer to retain their work while ensuring the
rest of their environment is consistently up-to-date on each workspace restart.

When a workspace is deleted, the control plane essentially runs a
[terraform destroy](https://www.terraform.io/cli/commands/destroy) to remove all
resources associated with the workspace.

> [!TIP]
> Terraform's
> [prevent-destroy](https://www.terraform.io/language/meta-arguments/lifecycle#prevent_destroy)
> and
> [ignore-changes](https://www.terraform.io/language/meta-arguments/lifecycle#ignore_changes)
> meta-arguments can be used to prevent accidental data loss.

## Coder apps

Additional IDEs, documentation, or services can be associated to your workspace
using the
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
resource.

![Coder Apps in the dashboard](../../../images/admin/templates/coder-apps-ui.png)

Note that some apps are associated to the agent by default as
[`display_apps`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#nested-schema-for-display_apps)
and can be hidden directly in the
[`coder_agent`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent)
resource. You can arrange the display orientation of Coder apps in your template
using [resource ordering](./resource-ordering.md).

### Coder app examples

<div class="tabs">

You can use these examples to add new Coder apps:

## code-server

```tf
resource "coder_app" "code-server" {
  agent_id     = coder_agent.main.id
  slug         = "code-server"
  display_name = "code-server"
  url          = "http://localhost:13337/?folder=/home/${local.username}"
  icon         = "/icon/code.svg"
  subdomain    = false
  share        = "owner"
}
```

## Filebrowser

```tf
resource "coder_app" "filebrowser" {
  agent_id     = coder_agent.main.id
  display_name = "file browser"
  slug         = "filebrowser"
  url          = "http://localhost:13339"
  icon         = "/icon/database.svg"
  subdomain    = true
  share        = "owner"
}
```

## Zed

```tf
resource "coder_app" "zed" {
    agent_id = coder_agent.main.id
    slug          = "slug"
    display_name  = "Zed"
    external = true
    url      = "zed://ssh/coder.${data.coder_workspace.me.name}"
    icon     = "/icon/zed.svg"
}
```

</div>

Check out our [module registry](https://registry.coder.com/modules) for
additional Coder apps from the team and our OSS community.

## Environment variables

Use the
[`coder_env`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/env)
resource to inject environment variables into workspace agents. Multiple
resources can target the same variable using
[merge strategies](./environment-variables.md) like `append` and `prepend`,
which is useful for building up `PATH`-style variables across modules.

See [Environment variables](./environment-variables.md) for details.

<a id="running-scripts-on-workspace-lifecycle"></a>

## Run scripts on workspace lifecycle events

The
[`coder_script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/script)
resource runs scripts during workspace lifecycle events like startup, stop, or
on a scheduled basis. It provides more control than the deprecated
`startup_script` field in `coder_agent`.

### When to use coder_script

- **Initialization tasks**: Install dependencies, clone repositories, configure
  services
- **Cleanup tasks**: Stop services gracefully on workspace stop
- **Scheduled maintenance**: Run periodic tasks via cron schedules
- **Blocking startup**: Wait for critical services before allowing user login

### Basic example

```tf
resource "coder_script" "install_dependencies" {
  agent_id           = coder_agent.main.id
  display_name       = "Install Dependencies"
  icon               = "/icon/package.svg"
  script             = <<-EOF
    #!/bin/sh
    set -e
    apt-get update
    apt-get install -y git curl
  EOF
  run_on_start       = true
  start_blocks_login = true
}
```

### Key features

- **Lifecycle control**: Run on start (`run_on_start`), stop (`run_on_stop`),
  or cron schedule (`cron`)
- **Login blocking**: Use `start_blocks_login = true` to ensure critical setup
  completes before user access
- **Timeouts**: Configure `timeout` for long-running scripts
- **Custom icons**: Display meaningful icons with the `icon` parameter
- **Log capture**: Script output is automatically captured and visible in the
  workspace UI

### Advanced patterns

Many [Coder modules](https://registry.coder.com/modules) use `coder_script`
internally. For example:

- [`git-clone`](https://registry.coder.com/modules/coder/git-clone): Clones
  repositories on startup
- [`dotfiles`](https://registry.coder.com/modules/coder/dotfiles): Applies user
  dotfiles
- [`code-server`](https://registry.coder.com/modules/coder/code-server):
  Installs and configures code-server (VS Code in the browser)

You can also reference external script files:

```tf
resource "coder_script" "init_docker" {
  agent_id     = coder_agent.main.id
  display_name = "Initialize Docker"
  script       = file("${path.module}/scripts/init-docker.sh")
  run_on_start = true
}
```

See the
[Coder Terraform provider documentation](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/script)
for complete reference.

<children></children>

---

# Agent metadata

Source: https://coder.com/docs/admin/templates/extending-templates/agent-metadata

![agent-metadata](../../../images/admin/templates/agent-metadata-ui.png)

You can show live operational metrics to workspace users with agent metadata. It
is the dynamic complement of [resource metadata](./resource-metadata.md).

You specify agent metadata in the
[`coder_agent`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent).

## Examples

All of these examples use
[heredoc strings](https://developer.hashicorp.com/terraform/language/expressions/strings#heredoc-strings)
for the script declaration. With heredoc strings, you can script without messy
escape codes, just as if you were working in your terminal.

Some of the examples use the [`coder stat`](../../../reference/cli/stat/index.md)
command. This is useful for determining CPU and memory usage of the VM or
container that the workspace is running in, which is more accurate than resource
usage about the workspace's host.

Here's a standard set of metadata snippets for Linux agents:

```tf
resource "coder_agent" "main" {
  os             = "linux"
  ...
  metadata {
    display_name = "CPU Usage"
    key  = "cpu"
    # Uses the coder stat command to get container CPU usage.
    script = "coder stat cpu"
    interval = 1
    timeout = 1
  }

  metadata {
    display_name = "Memory Usage"
    key  = "mem"
    # Uses the coder stat command to get container memory usage in GiB.
    script = "coder stat mem --prefix Gi"
    interval = 1
    timeout = 1
  }

  metadata {
    display_name = "CPU Usage (Host)"
    key  = "cpu_host"
    # calculates CPU usage by summing the "us", "sy" and "id" columns of
    # top.
    script = <<EOT
    top -bn1 | awk 'FNR==3 {printf "%2.0f%%", $2+$3+$4}'
    EOT
    interval = 1
    timeout = 1
  }

    metadata {
    display_name = "Memory Usage (Host)"
    key  = "mem_host"
    script = <<EOT
    free | awk '/^Mem/ { printf("%.0f%%", $4/$2 * 100.0) }'
    EOT
    interval = 1
    timeout = 1
  }

  metadata {
    display_name = "Disk Usage"
    key  = "disk"
    script = "df -h | awk '$6 ~ /^\\/$/ { print $5 }'"
    interval = 1
    timeout = 1
  }

  metadata {
    display_name = "Load Average"
    key  = "load"
    script = <<EOT
        awk '{print $1,$2,$3}' /proc/loadavg
    EOT
    interval = 1
    timeout = 1
  }
}
```

## Useful utilities

You can also show agent metadata for information about the workspace's host.

[top](https://manpages.ubuntu.com/manpages/jammy/en/man1/top.1.html) is
available in most Linux distributions and provides virtual memory, CPU and IO
statistics. Running `top` produces output that looks like:

```txt
%Cpu(s): 65.8 us,  4.4 sy,  0.0 ni, 29.3 id,  0.3 wa,  0.0 hi,  0.2 si,  0.0 st
MiB Mem :  16009.0 total,    493.7 free,   4624.8 used,  10890.5 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.  11021.3 avail Mem
```

[vmstat](https://manpages.ubuntu.com/manpages/jammy/en/man8/vmstat.8.html) is
available in most Linux distributions and provides virtual memory, CPU and IO
statistics. Running `vmstat` produces output that looks like:

```txt
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
0  0  19580 4781680 12133692 217646944    0    2     4    32    1    0  1  1 98  0  0
```

[dstat](https://manpages.ubuntu.com/manpages/jammy/man1/dstat.1.html) is
considerably more parseable than `vmstat` but often not included in base images.
It is easily installed by most package managers under the name `dstat`. The
output of running `dstat 1 1` looks like:

```txt
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read  writ| recv  send|  in   out | int   csw
1   1  98   0   0|3422k   25M|   0     0 | 153k  904k| 123k  174k
```

<a id="managing-the-database-load"></a>

## Manage the database load

Agent metadata can generate a significant write load and overwhelm your Coder
database if you're not careful. The approximate writes per second can be
calculated using the formula:

```txt
(metadata_count * num_running_agents * 2) / metadata_avg_interval
```

For example, let's say you have

- 10 running agents
- each with 6 metadata snippets
- with an average interval of 4&nbsp;seconds

You can expect `(10 * 6 * 2) / 4`, or 30 writes per second.

One of the writes is to the `UNLOGGED` `workspace_agent_metadata` table and the
other to the `NOTIFY` query that enables live stats streaming in the UI.

## Next Steps

- [Resource metadata](./resource-metadata.md)
- [Parameters](./parameters.md)

---

# Parameters

Source: https://coder.com/docs/admin/templates/extending-templates/parameters

A template can prompt the user for additional information when creating
workspaces with
[_parameters_](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter).

![Parameters in Create Workspace screen](../../../images/parameters.png)

The user can set parameters in the dashboard UI and CLI.

You'll likely want to hardcode certain template properties for workspaces, such
as security group. But you can let developers specify other properties with
parameters like instance size, geographical location, repository URL, etc.

This example lets a developer choose a Docker host for the workspace:

```tf
data "coder_parameter" "docker_host" {
  name        = "Region"
  description = "Which region would you like to deploy to?"
  icon        = "/emojis/1f30f.png"
  type        = "string"
  default     = "tcp://100.94.74.63:2375"

  option {
    name = "Pittsburgh, USA"
    value = "tcp://100.94.74.63:2375"
    icon = "/emojis/1f1fa-1f1f8.png"
  }

  option {
    name = "Helsinki, Finland"
    value = "tcp://100.117.102.81:2375"
    icon = "/emojis/1f1eb-1f1ee.png"
  }

  option {
    name = "Sydney, Australia"
    value = "tcp://100.127.2.1:2375"
    icon = "/emojis/1f1e6-1f1f9.png"
  }
}
```

From there, a template can refer to a parameter's value:

```tf
provider "docker" {
  host = data.coder_parameter.docker_host.value
}
```

## Types

A Coder parameter can have one of these types:

- `string`
- `bool`
- `number`
- `list(string)`

To specify a default value for a parameter with the `list(string)` type, use a
JSON array and the Terraform
[jsonencode](https://developer.hashicorp.com/terraform/language/functions/jsonencode)
function. For example:

```tf
data "coder_parameter" "security_groups" {
  name        = "Security groups"
  icon        = "/icon/aws.png"
  type        = "list(string)"
  description = "Select appropriate security groups."
  mutable     = true
  default = jsonencode([
    "Web Server Security Group",
    "Database Security Group",
    "Backend Security Group"
  ])
}
```

> [!NOTE]
> Overriding a `list(string)` on the CLI is tricky because:
>
> - `--parameter "parameter_name=parameter_value"` is parsed as CSV.
> - `parameter_value` is parsed as JSON.
>
> So, to properly specify a `list(string)` with the `--parameter` CLI argument,
> you will need to take care of both CSV quoting and shell quoting.
>
> For the above example, to override the default values of the `security_groups`
> parameter, you will need to pass the following argument to `coder create`:
>
> ```shell
> --parameter "\"security_groups=[\"\"DevOps Security Group\"\",\"\"Backend Security Group\"\"]\""
> ```
>
> Alternatively, you can use `--rich-parameter-file` to work around the above
> issues. This allows you to specify parameters as YAML. An equivalent parameter
> file for the above `--parameter` is provided below:
>
> ```yaml
> security_groups:
>   - DevOps Security Group
>   - Backend Security Group
> ```

## Options

A `string` parameter can provide a set of options to limit the user's choices:

```tf
data "coder_parameter" "docker_host" {
  name        = "Region"
  description = "Which region would you like to deploy to?"
  type        = "string"
  default     = "tcp://100.94.74.63:2375"

  option {
    name = "Pittsburgh, USA"
    value = "tcp://100.94.74.63:2375"
    icon = "/emojis/1f1fa-1f1f8.png"
  }

  option {
    name = "Helsinki, Finland"
    value = "tcp://100.117.102.81:2375"
    icon = "/emojis/1f1eb-1f1ee.png"
  }

  option {
    name = "Sydney, Australia"
    value = "tcp://100.127.2.1:2375"
    icon = "/emojis/1f1e6-1f1f9.png"
  }
}
```

### Incompatibility in Parameter Options for Workspace Builds

When creating Coder templates, authors have the flexibility to modify parameter
options associated with rich parameters. Such modifications can involve adding,
substituting, or removing a parameter option. It's important to note that making
these changes can lead to discrepancies in parameter values utilized by ongoing
workspace builds.

Consequently, workspace users will be prompted to select the new value from a
pop-up window or by using the command-line interface. While this additional
interactive step might seem like an interruption, it serves a crucial purpose.
It prevents workspace users from becoming trapped with outdated template
versions, ensuring they can smoothly update their workspace without any
hindrances.

Example:

- Bob creates a workspace using the `python-dev` template. This template has a
  parameter `image_tag`, and Bob selects `1.12`.
- Later, the template author Alice is notified of a critical vulnerability in a
  package installed in the `python-dev` template, which affects the image tag
  `1.12`.
- Alice remediates this vulnerability, and pushes an updated template version
  that replaces option `1.12` with `1.13` for the `image_tag` parameter. She
  then notifies all users of that template to update their workspace
  immediately.
- Bob saves their work, and selects the `Update` option in the UI. As their
  workspace uses the now-invalid option `1.12`, for the `image_tag` parameter,
  they are prompted to select a new value for `image_tag`.

## Required and optional parameters

A parameter is _required_ if it doesn't have the `default` property. The user
**must** provide a value to this parameter before creating a workspace:

```tf
data "coder_parameter" "account_name" {
  name        = "Account name"
  description = "Cloud account name"
  mutable     = true
}
```

If a parameter contains the `default` property, Coder will use this value if the
user does not specify any:

```tf
data "coder_parameter" "base_image" {
  name        = "Base image"
  description = "Base machine image to download"
  default     = "ubuntu:latest"
}
```

Admins can also set the `default` property to an empty value so that the
parameter field can remain empty:

```tf
data "coder_parameter" "dotfiles_url" {
  name        = "dotfiles URL"
  description = "Git repository with dotfiles"
  mutable     = true
  default     = ""
}
```

## Mutability

Immutable parameters can only be set in these situations:

- Creating a workspace for the first time.
- Updating a workspace to a new template version.
  This sets the initial value for required parameters.

The idea is to prevent users from modifying fragile or persistent workspace
resources like volumes, regions, and so on.

Example:

```tf
data "coder_parameter" "region" {
  name        = "Region"
  description = "Region where the workspace is hosted"
  mutable     = false
  default     = "us-east-1"
}
```

If a required parameter is empty or if the workspace creation page detects an incompatibility between selected
parameters, the **Create workspace** button is disabled until the issues are resolved.

## Ephemeral parameters

Ephemeral parameters are introduced to users in order to model specific
behaviors in a Coder workspace, such as reverting to a previous image, restoring
from a volume snapshot, or building a project without using cache. These
parameters are settable when creating, starting, updating, or restarting a workspace
but do not persist after the workspace is stopped.

Since these parameters are ephemeral in nature, subsequent builds proceed in the
standard manner:

```tf
data "coder_parameter" "force_rebuild" {
  name         = "force_rebuild"
  type         = "bool"
  description  = "Rebuild the Docker image rather than use the cached one."
  mutable      = true
  default      = false
  ephemeral    = true
}
```

<a id="validating-parameters"></a>

## Validate parameters

Coder supports parameters with multiple validation modes: min, max,
monotonic numbers, and regular expressions.

### Number

You can limit a `number` parameter to `min` and `max` boundaries.

You can also specify its monotonicity as `increasing` or `decreasing` to verify
the current and new values. Use the `monotonic` attribute for resources that
can't be shrunk or grown without implications, like disk volume size.

```tf
data "coder_parameter" "instances" {
  name        = "Instances"
  type        = "number"
  description = "Number of compute instances"
  validation {
    min       = 1
    max       = 8
    monotonic = "increasing"
  }
}
```

It is possible to override the default `error` message for a `number` parameter,
along with its associated `min` and/or `max` properties. The following message
placeholders are available `{min}`, `{max}`, and `{value}`.

```tf
data "coder_parameter" "instances" {
  name        = "Instances"
  type        = "number"
  description = "Number of compute instances"
  validation {
    min       = 1
    max       = 4
    error     = "Sorry, we can't provision too many instances - maximum limit: {max}, wanted: {value}."
  }
}
```

> [!NOTE]
> As of
> [`terraform-provider-coder` v0.19.0](https://registry.terraform.io/providers/coder/coder/0.19.0/docs),
> `options` can be specified in `number` parameters; this also works with
> validations such as `monotonic`.

### String

You can validate a `string` parameter to match a regular expression. The `regex`
property requires a corresponding `error` property.

```tf
data "coder_parameter" "project_id" {
  name        = "Project ID"
  description = "Alpha-numeric project ID"
  validation {
    regex = "^[a-z0-9]+$"
    error = "Unfortunately, this isn't a valid project ID"
  }
}
```

## Workspace presets

Workspace presets allow you to configure commonly used combinations of parameters
into a single option, which makes it easier for developers to pick one that fits
their needs.

![Template with options in the preset dropdown](../../../images/admin/templates/extend-templates/template-preset-dropdown.png)

Use the
[`coder_workspace_preset`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_preset)
data source to define the preset parameters. After you save the template file,
the presets will be available for all new workspace deployments.

### Optional preset fields

In addition to the required `name` and `parameters` fields, you can enhance your
workspace presets with optional `description` and `icon` fields:

- **description**: A helpful text description that provides additional context
  about the preset. This helps users understand what the preset is for and when
  to use it.
- **icon**: A visual icon displayed alongside the preset name in the UI. Use
  emoji icons with the format `/emojis/{code}.png` (e.g.,
  `/emojis/1f1fa-1f1f8.png` for the US flag emoji 🇺🇸).

For a complete list of all available fields, see the
[Terraform provider documentation](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_preset#schema).

<details><summary>Expand for an example</summary>

```tf
data "coder_workspace_preset" "goland-gpu" {
  name        = "GoLand with GPU"
  description = "Development workspace with GPU acceleration for GoLand IDE"
  icon        = "/emojis/1f680.png"
  parameters = {
    "machine_type"  = "n1-standard-1"
    "attach_gpu"    = "true"
    "gcp_region"    = "europe-west4-c"
    "jetbrains_ide" = "GO"
  }
}

data "coder_workspace_preset" "pittsburgh" {
  name        = "Pittsburgh"
  description = "Development workspace hosted in United States"
  icon        = "/emojis/1f1fa-1f1f8.png"
  parameters = {
    "region"       = "us-pittsburgh"
    "machine_type" = "n1-standard-2"
  }
}

data "coder_parameter" "machine_type" {
  name          = "machine_type"
  display_name  = "Machine Type"
  type          = "string"
  default       = "n1-standard-2"
}

data "coder_parameter" "attach_gpu" {
  name          = "attach_gpu"
  display_name  = "Attach GPU?"
  type          = "bool"
  default       = "false"
}

data "coder_parameter" "gcp_region" {
  name          = "gcp_region"
  display_name  = "GCP Region"
  type          = "string"
  default       = "us-central1-a"
}

data "coder_parameter" "jetbrains_ide" {
  name          = "jetbrains_ide"
  display_name  = "JetBrains IDE"
  type          = "string"
  default       = "IU"
}

data "coder_parameter" "region" {
  name          = "region"
  display_name  = "Region"
  type          = "string"
  default       = "us-east-1"
}
```

</details>

## Create Autofill

When the template doesn't specify default values, Coder may still autofill
parameters in one of two ways:

- Coder will look for URL query parameters with form `param.<name>=<value>`.

  This feature enables platform teams to create pre-filled template creation links.

- Coder can populate recently used parameter key-value pairs for the user.
  This feature helps reduce repetition when filling common parameters such as
  `dotfiles_url` or `region`.

  To enable this feature, you need to set the `auto-fill-parameters` experiment flag:

  ```sh
  coder server --experiments=auto-fill-parameters
  ```

  Or set the [environment variable](../../setup/index.md), `CODER_EXPERIMENTS=auto-fill-parameters`

## Dynamic Parameters

Coder v2.24.0 introduces [Dynamic Parameters](./dynamic-parameters.md) to extend the existing parameter system with
conditional form controls, enriched input types, and user identity awareness.
This feature allows template authors to create interactive workspace creation forms, meaning more environment
customization and fewer templates to maintain.

You can read more in the [Dynamic Parameters documentation](./dynamic-parameters.md) and try it out in the
[Parameters Playground](https://playground.coder.app/parameters).

---

# Dynamic Parameters

Source: https://coder.com/docs/admin/templates/extending-templates/dynamic-parameters

Coder v2.24.0 introduces Dynamic Parameters to extend Coder [parameters](./parameters.md) with conditional form controls,
enriched input types, and user identity awareness.
This allows template authors to create interactive workspace creation forms with more environment customization,
and that means fewer templates to maintain.

![Dynamic Parameters in Action](../../../images/admin/templates/extend-templates/dyn-params/dynamic-parameters-in-action.gif)

All parameters are parsed from Terraform, so your workspace creation forms live in the same location as your provisioning code.
You can use all the native Terraform functions and conditionality to create a self-service tooling catalog for every template.

Administrators can use Dynamic Parameters to:

- Create parameters which respond to the inputs of others.
- Only show parameters when other input criteria are met.
- Only show select parameters to target Coder roles or groups.

You can try the Dynamic Parameter syntax and any of the code examples below in the
[Parameters Playground](https://playground.coder.app/parameters).
You should experiment with parameters in the playground before you upgrade live templates.

## When You Should Upgrade to Dynamic Parameters

While Dynamic parameters introduce a variety of new powerful tools, all functionality is backwards compatible with
existing coder templates.
When you opt-in to the new experience, no functional changes will be applied to your production parameters.

Some reasons Coder template admins should try Dynamic Parameters:

- You maintain or support many templates for teams with unique expectations or use cases.
- You want to selectively expose privileged workspace options to admins, power users, or personas.
- You want to make the workspace creation flow more ergonomic for developers.

Dynamic Parameters help you reduce template duplication by setting the conditions for which users should see specific parameters.
They reduce the potential complexity of user-facing configuration by allowing administrators to organize a long list of options into interactive, branching paths for workspace customization.
They allow you to set resource guardrails by referencing Coder identity in the `coder_workspace_owner` data source.

## How to use Dynamic Parameters

Dynamic Parameters is the standard workspace creation experience.
In Coder v2.25.0 and later it is enabled automatically, and the classic parameter flow is deprecated.

To use the features described on this page in an existing template:

1. Update your template to use version >=2.4.0 of the Coder provider with the following Terraform block.

   ```tf
   terraform {
     required_providers {
       coder = {
         source = "coder/coder"
         version = ">=2.4.0"
       }
     }
   }
   ```

1. Add some [conditional parameters](#available-form-input-types).

   Note that these new features must be declared in your Terraform to start leveraging Dynamic Parameters.

1. Save and publish the template.

1. Users should see the updated workspace creation form.

Dynamic Parameters are backwards compatible: switching a template does not change how its existing parameters behave.
If a template's active version was published before Dynamic Parameters, publish a new version to generate the metadata the new form requires.

## Upgrade from parameter compatibility mode

Parameter compatibility mode keeps a template on the classic parameter flow.
Coder maintains a separate code path for that flow. It will be removed in a future release, so templates that
use compatibility mode need to be upgraded before then.

To find templates that use compatibility mode, open the **Templates** page and select the
**Templates using compatibility mode** filter, or search for `compatibility_mode:true`.

For each template:

1. Confirm your versions meet the requirements:

   - `coder/coder`: >= [v2.25.0](https://github.com/coder/coder/releases/tag/v2.25.0)
   - `coder/terraform-provider-coder`: >= [v2.5.3](https://github.com/coder/terraform-provider-coder/releases/tag/v2.5.3)

1. Select **Settings** > **Parameters** on the template, then clear
   **Use parameter compatibility mode for workspace builds**.

1. Publish a new template version so Coder can resolve the parameter metadata.
   If you don't need to change the Terraform, [refresh the template data](../managing-templates/index.md#refresh-template-data)
   to publish a new version from the existing source files.

1. Open the workspace creation form and confirm the parameters render as expected.

You can make the same change through the `use_classic_parameter_flow` field in the
[templates API](../../../reference/api/templates.md#update-template-settings-by-id).

If a template does not work after the switch, you can [revert it to compatibility mode](#revert-to-classic-parameters)
and [file an issue](https://github.com/coder/coder/issues/new?labels=parameters) with the `parameters` label.

## Data sources and cached template data

Coder reads Terraform `data` sources once, when it imports a template version, and stores the results.
Rendering the form evaluates your parameter expressions against those stored results, so a `data` source whose underlying value changes in your cloud or cluster keeps returning the imported value.

The `coder_workspace_owner` data source is the exception.
Coder substitutes the identity of the user filling in the form each time it renders, which is what makes [Identity-Aware Parameters](#identity-aware-parameters-premium) work.

To pick up a change to any other `data` source, [refresh the template data](../managing-templates/index.md#refresh-template-data).
This imports the active version's source files again and publishes the result as a new active version.

## Features and Capabilities

Dynamic Parameters introduces three primary enhancements to the standard parameter system:

- **Conditional Parameters**

  - Parameters can respond to changes in other parameters
  - Show or hide parameters based on other selections
  - Modify validation rules conditionally
  - Create branching paths in workspace creation forms

- **Reference User Properties**

  - Read user data at build time from [`coder_workspace_owner`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_owner)
  - Conditionally hide parameters based on user's role
  - Change parameter options based on user groups
  - Reference user name, groups, and roles in parameter text

- **Additional Form Inputs**

  - Searchable dropdown lists for easier selection
  - Multi-select options for choosing multiple items
  - Secret text inputs for sensitive information
  - Slider input for disk size, model temperature
  - Disabled parameters to display immutable data

> [!IMPORTANT]
> Dynamic Parameters does not support external data fetching via HTTP endpoints at workspace build time.
>
> External fetching would introduce unpredictability in workspace builds after publishing a template.
> Instead, we recommend that template administrators pull in any required data for a workspace build as a
> [locals](https://developer.hashicorp.com/terraform/tutorials/configuration-language/locals) or JSON file,
> then reference that data in Terraform.
>
> If you have a use case for external data fetching, please file an issue or create a discussion in the
> [Coder GitHub repository](https://github.com/coder/coder).

## Available Form Input Types

Dynamic Parameters supports a variety of form types to create rich, interactive user experiences.

![Old vs New Parameters](../../../images/admin/templates/extend-templates/dyn-params/dynamic-params-compare.png)

Different parameter types support different form types.
You can specify the form type using the
[`form_type`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter#form_type-1) attribute.

The **Options** column in the table below indicates whether the form type supports options (**Yes**) or doesn't support them (**No**).
When supported, you can specify options using one or more `option` blocks in your parameter definition,
where each option has a `name` (displayed to the user) and a `value` (used in your template logic).

| Form Type      | Parameter Types                            | Options | Notes                                                                                                                   |
|----------------|--------------------------------------------|---------|-------------------------------------------------------------------------------------------------------------------------|
| `radio`        | `string`, `number`, `bool`, `list(string)` | Yes     | Radio buttons for selecting a single option with all choices visible at once. <br />The classic parameter option.       |
| `dropdown`     | `string`, `number`                         | Yes     | Choose a single option from a searchable dropdown list. <br />Default for `string` or `number` parameters with options. |
| `multi-select` | `list(string)`                             | Yes     | Select multiple items from a searchable dropdown list. <br />Selected items are shown as removable chips.               |
| `tag-select`   | `list(string)`                             | No      | Default for `list(string)` parameters without options.                                                                  |
| `input`        | `string`, `number`                         | No      | Standard single-line text input field. <br />Default for `string/number` parameters without options.                    |
| `textarea`     | `string`                                   | No      | Multi-line text input field for longer content.                                                                         |
| `slider`       | `number`                                   | No      | Slider selection with min/max validation for numeric values.                                                            |
| `checkbox`     | `bool`                                     | No      | A single checkbox for boolean parameters. <br />Default for boolean parameters.                                         |

### Available Styling Options

The `coder_parameter` resource supports an additional `styling` attribute for special cosmetic changes that can be used
to further customize the workspace creation form.

This can be used for:

- Masking private inputs
- Marking inputs as read-only
- Setting placeholder text

Note that the `styling` attribute should not be used as a governance tool, since it only changes how the interactive
form is displayed.
Users can avoid restrictions like `disabled` if they create a workspace via the CLI.

This attribute accepts JSON like so:

```tf
data "coder_parameter" "styled_parameter" {
  ...
  styling = jsonencode({
    disabled = true
  })
}
```

Not all styling attributes are supported by all form types, use the reference below for syntax:

| Styling Option | Compatible parameter types | Compatible form types | Notes                                                                               |
|----------------|----------------------------|-----------------------|-------------------------------------------------------------------------------------|
| `disabled`     | All parameter types        | All form types        | Disables the form control when `true`.                                              |
| `placeholder`  | `string`                   | `input`, `textarea`   | Sets placeholder text. <br />This is overwritten by user entry.                     |
| `mask_input`   | `string`, `number`         | `input`, `textarea`   | Masks inputs as asterisks (`*`). Used to cosmetically hide token or password entry. |

## Use Case Examples

### New Form Types

The following examples show some basic usage of the
[`form_type`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter#form_type-1)
attribute [explained above](#available-form-input-types).
These are used to change the input style of form controls in the create workspace form.

<div class="tabs">

### Dropdowns

Single-select parameters with options can use the `form_type="dropdown"` attribute for better organization.

[Try dropdown lists on the Parameter Playground](https://playground.coder.app/parameters/kgNBpjnz7x)

```tf
locals {
  ides = [
    "VS Code",
    "JetBrains IntelliJ",
    "PyCharm",
    "GoLand",
    "WebStorm",
    "Vim",
    "Emacs",
    "Neovim"
  ]
}

data "coder_parameter" "ides_dropdown" {
  name = "ides_dropdown"
  display_name = "Select your IDEs"
  type = "string"

  form_type = "dropdown"

  dynamic "option" {
    for_each = local.ides
    content {
      name  = option.value
      value = option.value
    }
  }
}
```

### Text Area

The large text entry option can be used to enter long strings like AI prompts, scripts, or natural language.

[Try textarea parameters on the Parameter Playground](https://playground.coder.app/parameters/RCAHA1Oi1_)

```tf

data "coder_parameter" "text_area" {
  name = "text_area"
  description  = "Enter multi-line text."
  mutable      = true
  display_name = "Textarea"

  form_type = "textarea"
  type      = "string"

  default = <<-EOT
    This is an example of multi-line text entry.

    The 'textarea' form_type is useful for
    - AI prompts
    - Scripts
    - Read-only info (try the 'disabled' styling option)
  EOT
}

```

### Multi-select

Multi-select parameters allow users to select one or many options from a single list of options.
For example, adding multiple IDEs with a single parameter.

[Try multi-select parameters on the Parameter Playground](https://playground.coder.app/parameters/XogX54JV_f)

```tf
locals {
  ides = [
    "VS Code", "JetBrains IntelliJ",
    "GoLand", "WebStorm",
    "Vim", "Emacs",
    "Neovim", "PyCharm",
    "Databricks", "Jupyter Notebook",
  ]
}

data "coder_parameter" "ide_selector" {
  name = "ide_selector"
  description  = "Choose any IDEs for your workspace."
  mutable      = true
  display_name = "Select multiple IDEs"


  # Allows users to select multiple IDEs from the list.
  form_type = "multi-select"
  type      = "list(string)"


  dynamic "option" {
    for_each = local.ides
    content {
      name  = option.value
      value = option.value
    }
  }
}
```

### Radio

Radio buttons are used to select a single option with high visibility.
This is the original styling for list parameters.

[Try radio parameters on the Parameter Playground](https://playground.coder.app/parameters/3OMDp5ANZI).

```tf
data "coder_parameter" "environment" {
  name         = "environment"
  display_name = "Environment"
  description  = "An example of environment listing with the radio form type."
  type         = "string"
  default      = "dev"

  form_type    = "radio"

  option {
    name  = "Development"
    value = "dev"
  }
  option {
    name  = "Experimental"
    value = "exp"
  }
  option {
    name  = "Staging"
    value = "staging"
  }
  option {
    name  = "Production"
    value = "prod"
  }
}
```

### Checkboxes

A single checkbox for boolean values.
This can be used for a TOS confirmation or to expose advanced options.

[Try checkbox parameters on the Parameters Playground](https://playground.coder.app/parameters/ycWuQJk2Py).

```tf
data "coder_parameter" "enable_gpu" {
  name         = "enable_gpu"
  display_name = "Enable GPU"
  type         = "bool"
  form_type    = "checkbox" # This is the default for boolean parameters
  default      = false
}
```

### Slider

Sliders can be used for configuration on a linear scale, like resource allocation.
The `validation` block is used to constrain (or clamp) the minimum and maximum values for the parameter.

[Try slider parameters on the Parameters Playground](https://playground.coder.app/parameters/RsBNcWVvfm).

```tf
data "coder_parameter" "cpu_cores" {
  name         = "cpu_cores"
  display_name = "CPU Cores"
  type         = "number"
  form_type    = "slider"
  default      = 2
  validation {
    min = 1
    max = 8
  }
}
```

### Masked Input

Masked input parameters can be used to visually hide secret values in the workspace creation form.
Note that this does not secure information on the backend and is purely cosmetic.

[Try private parameters on the Parameters Playground](https://playground.coder.app/parameters/wmiP7FM3Za).

Note: This text may not be properly hidden in the Playground.
The `mask_input` styling attribute is supported in v2.24.0 and later.

```tf
data "coder_parameter" "private_api_key" {
  name         = "private_api_key"
  display_name = "Your super secret API key"
  type         = "string"

  form_type = "input" # | "textarea"

  # Will render as "**********"
  default = "privatekey"

  styling = jsonencode({
    mask_input = true
  })
}
```

</div>

### Conditional Parameters

Using native Terraform syntax and parameter attributes like `count`, we can allow some parameters to react to user inputs.

This means:

- Hiding parameters unless activated
- Conditionally setting default values
- Changing available options based on other parameter inputs

Use these in conjunction to build intuitive, reactive forms for workspace creation.

<div class="tabs">

### Hide/Show Options

Use Terraform conditionals and the `count` block to allow a checkbox to expose or hide a subsequent parameter.

[Try conditional parameters on the Parameter Playground](https://playground.coder.app/parameters/xmG5MKEGNM).

```tf
data "coder_parameter" "show_cpu_cores" {
  name         = "show_cpu_cores"
  display_name = "Toggles next parameter"
  description  = "Select this checkbox to show the CPU cores parameter."
  type         = "bool"
  form_type    = "checkbox"
  default      = false
  order        = 1
}

data "coder_parameter" "cpu_cores" {
  # Only show this parameter if the previous box is selected.
  count = data.coder_parameter.show_cpu_cores.value ? 1 : 0

  name         = "cpu_cores"
  display_name = "CPU Cores"
  type         = "number"
  form_type    = "slider"
  default      = 2
  order        = 2
  validation {
    min = 1
    max = 8
  }
}
```

### Dynamic Defaults

Influence which option is selected by default for one parameter based on the selection of another.
This allows you to suggest an option dynamically without strict enforcement.

[Try dynamic defaults in the Parameter Playground](https://playground.coder.app/parameters/DEi-Bi6DVe).

```tf
locals {
  ides = [
    "VS Code",
    "IntelliJ", "GoLand",
    "WebStorm", "PyCharm",
    "Databricks", "Jupyter Notebook",
  ]
  mlkit_ides = jsonencode(["Databricks", "PyCharm"])
  core_ides = jsonencode(["VS Code", "GoLand"])
}

data "coder_parameter" "git_repo" {
  name = "git_repo"
  display_name = "Git repo"
  description = "Select a git repo to work on."
  order = 1
  mutable = true
  type = "string"
  form_type = "dropdown"

  option {
    # A Go-heavy repository
    name = "coder/coder"
    value = "coder/coder"
  }

  option {
    # A python-heavy repository
    name = "coder/mlkit"
    value = "coder/mlkit"
  }
}

data "coder_parameter" "ide_selector" {
  # Conditionally expose this parameter
  count = try(data.coder_parameter.git_repo.value, "") != "" ? 1 : 0

  name = "ide_selector"
  description  = "Choose any IDEs for your workspace."
  order        = 2
  mutable      = true

  display_name = "Select IDEs"
  form_type = "multi-select"
  type      = "list(string)"
  default   = try(data.coder_parameter.git_repo.value, "") == "coder/mlkit" ? local.mlkit_ides : local.core_ides


  dynamic "option" {
    for_each = local.ides
    content {
      name  = option.value
      value = option.value
    }
  }
}
```

## Dynamic Validation

A parameter's validation block can leverage inputs from other parameters.

[Try dynamic validation in the Parameter Playground](https://playground.coder.app/parameters/sdbzXxagJ4).

```tf
data "coder_parameter" "git_repo" {
  name = "git_repo"
  display_name = "Git repo"
  description = "Select a git repo to work on."
  order = 1
  mutable = true
  type = "string"
  form_type = "dropdown"

  option {
    # A Go-heavy repository
    name = "coder/coder"
    value = "coder/coder"
  }

  option {
    # A python-heavy repository
    name = "coder/mlkit"
    value = "coder/mlkit"
  }
}

data "coder_parameter" "cpu_cores" {
  name         = "cpu_cores"
  display_name = "CPU Cores"
  type         = "number"
  form_type    = "slider"
  order        = 2

  # Dynamically set default
  default      = try(data.coder_parameter.git_repo.value, "") == "coder/mlkit" ? 12 : 6

  validation {
    min = 1

    # Dynamically set max validation
    max = try(data.coder_parameter.git_repo.value, "") == "coder/mlkit" ? 16 : 8
  }
}
```

<!-- ## Daisy Chaining

You can daisy-chain the conditionals shown here to create a dynamically expanding form.
Note that parameters must be indexed when using the `count` attribute.

[Try daisy-chaining parameters in the Parameter Playground](https://playground.coder.app/parameters/jLUUhoDLIa).

```tf

locals {
  ides = [
    "VS Code",
    "JetBrains IntelliJ",
    "GoLand",
    "WebStorm",
    "PyCharm",
    "Databricks",
    "Jupyter Notebook",
  ]

  is_ml_repo = data.coder_parameter.git_repo == "coder/mlkit"

  selected = jsondecode(data.coder_parameter.ide_selector[0].value)

  # selected = try(jsondecode(data.coder_parameter.ide_selector[0].value), [])
}

data "coder_parameter" "git_repo" {
  name = "git_repo"
  display_name = "Git repo"
  description = "Select a git repo to work on."
  order = 1
  mutable = true
  type = "string"
  form_type = "dropdown"

  option {
    name = "coder/coder"
    value = "coder/coder"
  }

  option {
    name = "coder/mlkit"
    value = "coder/mlkit"
  }
}

data "coder_parameter" "ide_selector" {
  # Only show this parameter if a git repo has been selected.
  count = try(data.coder_parameter.git_repo.value, "") != "" ? 1 : 0
  name = "ide_selector"
  description  = "Choose any IDEs for your workspace."
  mutable      = true
  display_name = "Select multiple IDEs"
  order = 1
  default = "[]"

  # Allows users to select multiple IDEs from the list.
  form_type = "multi-select"
  type      = "list(string)"

  dynamic "option" {
    for_each = local.ides
    content {
      name  = option.value
      value = option.value
    }
  }
}

data "coder_parameter" "cpu_cores" {
  # Only show this parameter if the IDEs have been selected.
  count = length(local.selected) > 0 ? 1 : 0

  name         = "cpu_cores"
  display_name = "CPU Cores"
  type         = "number"
  form_type    = "slider"
  default      = local.is_ml_repo ? 12 : 6
  order        = 2
  validation {
    min = 1
    max = local.is_ml_repo ? 16 : 8
  }
}
``` -->

</div>

## Identity-Aware Parameters (Premium)

Premium users can leverage our roles and groups to conditionally expose or change parameters based on user identity.
This is helpful for establishing governance policy directly in the workspace creation form,
rather than creating multiple templates to manage RBAC.

User identity is referenced in Terraform by reading the
[`coder_workspace_owner`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_owner) data source.

<div class="tabs">

### Role-aware Options

Template administrators often want to expose certain experimental or unstable options only to those with elevated roles.
You can now do this by setting `count` based on a user's group or role, referencing the
[`coder_workspace_owner`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_owner)
data source.

[Try out admin-only options in the Playground](https://playground.coder.app/parameters/5Gn9W3hYs7).

```tf

locals {
  roles = [for r in data.coder_workspace_owner.me.rbac_roles: r.name]
  is_admin = contains(data.coder_workspace_owner.me.groups, "admin")
  has_admin_role = contains(local.roles, "owner")
}

data "coder_workspace_owner" "me" {}

data "coder_parameter" "advanced_settings" {
  # This parameter is only visible when the user is an administrator
  count = local.is_admin ? 1 : 0

  name         = "advanced_settings"
  display_name = "Add an arbitrary script"
  description  = "An advanced configuration option only available to admins."
  type         = "string"
  form_type    = "textarea"
  mutable      = true
  order        = 5

  styling = jsonencode({
    placeholder = <<-EOT
  #!/usr/bin/env bash
  while true; do
    echo "hello world"
    sleep 1
  done
  EOT
  })
}

```

### Group-aware Regions

You can expose regions depending on which group a user belongs to.
This way developers can't accidentally induce low-latency with world-spanning connections.

[Try user-aware regions in the parameter playground](https://playground.coder.app/parameters/tBD-mbZRGm)

```tf

locals {
  eu_regions = [
    "eu-west-1 (Ireland)",
    "eu-central-1 (Frankfurt)",
    "eu-north-1 (Stockholm)",
    "eu-west-3 (Paris)",
    "eu-south-1 (Milan)"
  ]

  us_regions = [
    "us-east-1 (N. Virginia)",
    "us-west-1 (California)",
    "us-west-2 (Oregon)",
    "us-east-2 (Ohio)",
    "us-central-1 (Iowa)"
  ]

  eu_group_name = "eu-helsinki"
  is_eu_dev = contains(data.coder_workspace_owner.me.groups, local.eu_group_name)
  region_desc_tag = local.is_eu_dev ? "european" : "american"
}

data "coder_parameter" "region" {
  name         = "region"
  display_name = "Select a Region"
  description  = "Select from ${local.region_desc_tag} region options."
  type         = "string"
  form_type    = "dropdown"
  order        = 5
  default      = local.is_eu_dev ? local.eu_regions[0] : local.us_regions[0]

  dynamic "option" {
    for_each = local.is_eu_dev ? local.eu_regions : local.us_regions
    content {
      name        = option.value
      value       = option.value
      description = "Use ${option.value}"
    }
  }
}
```

### Groups As Namespaces

A slightly unorthodox way to leverage this is by filling the selections of a parameter from the user's groups.
Some users associate groups with namespaces, such as Kubernetes, then allow users to target that namespace with a parameter.

[Try groups as options in the Parameter Playground](https://playground.coder.app/parameters/lKbU53nYjl).

```tf
locals {
  groups = data.coder_workspace_owner.me.groups
}

data "coder_workspace_owner" "me" {}

data "coder_parameter" "your_groups" {
  type         = "string"
  name         = "your_groups"
  display_name = "Your Coder Groups"
  description  = "Select your namespace..."
  default      = "target-${local.groups[0]}"
  mutable      = true
  form_type = "dropdown"

  dynamic "option" {
    # options populated directly from groups
    for_each = local.groups
    content {
      name  = option.value
      # Native terraform be used to decorate output
      value = "target-${option.value}"
    }
  }
}
```

</div>

## Troubleshooting

Dynamic Parameters is now in general availability. We're tracking a list of known issues [here in Github](https://github.com/coder/coder/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20label%3Aparameters) as we continue to polish and improve the workflow.
If you have any issues during upgrade, please file an issue in our
[GitHub repository](https://github.com/coder/coder/issues/new?labels=parameters) with the `parameters` label and include a
[Playground link](https://playground.coder.app/parameters) where applicable.
We appreciate the feedback and look forward to what the community creates with this system!

You can also [search or track the list of known issues](https://github.com/coder/coder/issues?q=is%3Aissue%20state%3Aopen%20label%3Aparameters).

You can share anything you build with Dynamic Parameters in our [Discord](https://coder.com/chat).

### Enabled Dynamic Parameters, but my template looks the same

Ensure that the following version requirements are met:

- `coder/coder`: >= [v2.25.0](https://github.com/coder/coder/releases/tag/v2.25.0)
- `coder/terraform-provider-coder`: >= [v2.5.3](https://github.com/coder/terraform-provider-coder/releases/tag/v2.5.3)

Enabling Dynamic Parameters on an existing template requires administrators to publish a new template version.
This will resolve the necessary template metadata to render the form.
To publish one without editing the template's Terraform, [refresh the template data](../managing-templates/index.md#refresh-template-data).

### Revert to classic parameters

The classic parameter flow is deprecated and will be removed in a future release.
If a template does not work with Dynamic Parameters, you can opt that template out.
Select **Settings** > **Parameters** on the template, then select **Use parameter compatibility mode for workspace builds**.
You can also set the `use_classic_parameter_flow` field through the
[templates API](../../../reference/api/templates.md#update-template-settings-by-id).

If your template's parameters do not work with Dynamic Parameters, please
[file an issue](https://github.com/coder/coder/issues/new?labels=parameters) with the `parameters` label.

### Template variables not showing up

Dynamic Parameters are GA as of [v2.25.0](https://github.com/coder/coder/releases/tag/v2.25.0). Template variables are fully supported in Dynamic Parameters.

If you are experiencing issues with template variables, try upgrading to the latest version. Otherwise, please file an issue in our Github.

### Can I use registry modules with Dynamic Parameters?

Yes, registry modules are supported with Dynamic Parameters.

Unless explicitly mentioned, no registry modules require Dynamic Parameters.
Later in 2025, more registry modules will be converted to Dynamic Parameters to improve their UX.

In the meantime, you can safely convert existing templates and build new parameters on top of the functionality provided in the registry.

### "Module not loaded" errors when using Dynamic Parameters

Dynamic Parameters require Terraform modules to be archived and stored in the database. Coder limits module archives to **20&nbsp;MB total** to prevent database bloat. If your template uses modules that exceed this limit, some modules will be unavailable for parameter declarations.

**Symptoms:**

You may see warnings in the provisioner logs:

```txt
[API] 2026-01-29 22:00:22.691 [warn]  provisionerd-nixos-0.executor: some (or all) terraform modules were not archived, template will have reduced function  skipped_modules=large:git::https://github.com/coder/large-module.git
```

If encountered, reduce the size of the module by removing unnecessary files.

You can hit the same error for a different reason: if the active template
version has no cached module archive at all, the workspace creation form
shows a warning for every module in the template, for example:

```txt
Module not loaded. Did you run `terraform init`?
Module 'jetbrains' in file "main.tf:149,1-19" cannot be resolved. This module will be ignored.
```

This happens for template versions published before Coder started archiving
modules for Dynamic Parameters. **Workspace builds still succeed**, since
Terraform fetches modules from their original sources during the build
regardless of the cache; only the form's ability to evaluate module-backed
parameter values is affected. To fix it,
[publish a new template version](../managing-templates/index.md#refresh-template-data),
which re-runs `terraform init` and populates the archive for that version.

This archive is the same one Coder reuses across workspace builds to avoid
re-downloading modules. See [module caching](./modules.md#module-caching) for
how to disable that behavior for a template.

---

# Prebuilt workspaces

Source: https://coder.com/docs/admin/templates/extending-templates/prebuilt-workspaces

Prebuilt workspaces (prebuilds) reduce workspace creation time with an automatically-maintained pool of
ready-to-use workspaces for specific parameter presets.

The template administrator defines the prebuilt workspace's parameters and number of instances to keep provisioned.
The desired number of workspaces are then provisioned transparently.
When a developer creates a new workspace that matches the definition, Coder assigns them an existing prebuilt workspace.
This significantly reduces wait times, especially for templates with complex provisioning or lengthy startup procedures.

Prebuilt workspaces are:

- Created and maintained automatically by Coder to match your specified preset configurations.
- Claimed transparently when developers create workspaces.
- Monitored and replaced automatically to maintain your desired pool size.
- Automatically scaled based on time-based schedules to optimize resource usage.

Prebuilt workspaces are a special type of workspace that don't follow the
[regular workspace scheduling features](../../../user-guides/workspace-scheduling.md) like autostart and autostop. Instead, they have their own reconciliation loop that handles prebuild-specific scheduling features such as TTL and prebuild scheduling.

## Relationship to workspace presets

Prebuilt workspaces are tightly integrated with [workspace presets](./parameters.md#workspace-presets):

1. Each prebuilt workspace is associated with a specific template preset.
1. The preset must define all required parameters needed to build the workspace.
1. The preset parameters define the base configuration and are immutable once a prebuilt workspace is provisioned.
1. Parameters that are not defined in the preset can still be customized by users when they claim a workspace.
1. If a user does not select a preset but provides parameters that match one or more presets, Coder will automatically select the most specific matching preset and assign a prebuilt workspace if one is available.

## Prerequisites

- [**Premium license**](../../../install/prepare/licensing.md)
- **Compatible Terraform provider**: Use `coder/coder` Terraform provider `>= 2.4.1`.

## Enable prebuilt workspaces for template presets

In your template, add a `prebuilds` block within a `coder_workspace_preset` definition to identify the number of prebuilt
instances your Coder deployment should maintain, and optionally configure a `expiration_policy` block to set a TTL
(Time To Live) for unclaimed prebuilt workspaces to ensure stale resources are automatically cleaned up.

   ```tf
   data "coder_workspace_preset" "goland" {
     name = "GoLand: Large"
     parameters = {
       jetbrains_ide = "GO"
       cpus          = 8
       memory        = 16
     }
     prebuilds {
       instances = 3   # Number of prebuilt workspaces to maintain
       expiration_policy {
          ttl = 86400  # Time (in seconds) after which unclaimed prebuilds are expired (86400 = 1 day)
      }
     }
   }
   ```

After you publish a new template version, Coder will automatically provision and maintain prebuilt workspaces through an
internal reconciliation loop (similar to Kubernetes) to ensure the defined `instances` count are running.

The `expiration_policy` block ensures that any prebuilt workspaces left unclaimed for more than `ttl` seconds is considered
expired and automatically cleaned up.

## Prebuilt workspace lifecycle

Prebuilt workspaces follow a specific lifecycle from creation through eligibility to claiming.

1. After you configure a preset with prebuilds and publish the template, Coder provisions the prebuilt workspace(s).

   1. Coder automatically creates the defined `instances` count of prebuilt workspaces.
   1. Each new prebuilt workspace is initially owned by an unprivileged system pseudo-user named `prebuilds`.
      - The `prebuilds` user belongs to the `Everyone` group (you can add it to additional groups if needed).
   1. Each prebuilt workspace receives a randomly generated name for identification.
   1. The workspace is provisioned like a regular workspace; only its ownership distinguishes it as a prebuilt workspace.

1. Prebuilt workspaces start up and become eligible to be claimed by a developer.

   Before a prebuilt workspace is available to users:

   1. The workspace is provisioned.
   1. The agent starts up and connects to coderd.
   1. The agent starts its bootstrap procedures and completes its startup scripts.
   1. The agent reports `ready` status.

      After the agent reports `ready`, the prebuilt workspace considered eligible to be claimed.

   Prebuilt workspaces that fail during provisioning are retried with a backoff to prevent transient failures.

1. When a developer creates a new workspace, the claiming process occurs:

   1. Developer selects a template and preset that has prebuilt workspaces configured.
   1. If an eligible prebuilt workspace exists, ownership transfers from the `prebuilds` user to the requesting user.
   1. The workspace name changes to the user's requested name.
   1. `terraform apply` is executed using the new ownership details, which may affect the [`coder_workspace`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace) and
      [`coder_workspace_owner`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace_owner)
      datasources (see [Prevent resource replacement](#prevent-resource-replacement) for further considerations).

   The claiming process is transparent to the developer — the workspace will just be ready faster than usual.

You can view available prebuilt workspaces in the **Workspaces** view in the Coder dashboard:

![A prebuilt workspace in the dashboard](../../../images/admin/templates/extend-templates/prebuilt/prebuilt-workspaces.png)
_Note the search term `owner:prebuilds`._

Unclaimed prebuilt workspaces can be interacted with in the same way as any other workspace.
However, if a Prebuilt workspace is stopped, the reconciliation loop will not destroy it.
This gives template admins the ability to park problematic prebuilt workspaces in a stopped state for further investigation.

### Expiration Policy

Prebuilt workspaces support expiration policies through the `ttl` setting inside the `expiration_policy` block.
This value defines the Time To Live (TTL) of a prebuilt workspace, i.e., the duration in seconds that an unclaimed
prebuilt workspace can remain before it is considered expired and eligible for cleanup.

Expired prebuilt workspaces are removed during the reconciliation loop to avoid stale environments and resource waste.
New prebuilt workspaces are only created to maintain the desired count if needed.

### Scheduling

Prebuilt workspaces support time-based scheduling to scale the number of instances up or down.
This allows you to reduce resource costs during off-hours while maintaining availability during peak usage times.

Configure scheduling by adding a `scheduling` block within your `prebuilds` configuration:

```tf
data "coder_workspace_preset" "goland" {
   name = "GoLand: Large"
   parameters = {
     jetbrains_ide = "GO"
     cpus          = 8
     memory        = 16
   }

   prebuilds {
     instances = 0                  # default to 0 instances

     scheduling {
       timezone = "UTC"             # only a single timezone may be used for simplicity

       # scale to 3 instances during the work week
       schedule {
         cron = "* 8-18 * * 1-5"    # from 8AM-6:59PM, Mon-Fri, UTC
         instances = 3              # scale to 3 instances
       }

       # scale to 1 instance on Saturdays for urgent support queries
       schedule {
         cron = "* 8-14 * * 6"      # from 8AM-2:59PM, Sat, UTC
         instances = 1              # scale to 1 instance
       }
     }
   }
}
```

**Scheduling configuration:**

- `timezone`: (Required) The timezone for all cron expressions. Only a single timezone is supported per scheduling configuration.
- `schedule`: One or more schedule blocks defining when to scale to specific instance counts.
  - `cron`: (Required) Cron expression interpreted as continuous time ranges.
  - `instances`: (Required) Number of prebuilt workspaces to maintain during this schedule.

**How scheduling works:**

1. The reconciliation loop evaluates all active schedules every reconciliation interval (`CODER_WORKSPACE_PREBUILDS_RECONCILIATION_INTERVAL`).
1. The schedule that matches the current time becomes active. Overlapping schedules are disallowed by validation rules.
1. If no schedules match the current time, the base `instances` count is used.
1. The reconciliation loop automatically creates or destroys prebuilt workspaces to match the target count.

**Cron expression format:**

Cron expressions follow the format: `* HOUR DOM MONTH DAY-OF-WEEK`

- `*` (minute): Must always be `*` to ensure the schedule covers entire hours rather than specific minute intervals
- `HOUR`: 0-23, range (e.g., 8-18 for 8AM-6:59PM), or `*`
- `DOM` (day-of-month): 1-31, range, or `*`
- `MONTH`: 1-12, range, or `*`
- `DAY-OF-WEEK`: 0-6 (Sunday=0, Saturday=6), range (e.g., 1-5 for Monday to Friday), or `*`

**Important notes about cron expressions:**

- **Minutes must always be `*`**: To ensure the schedule covers entire hours
- **Time ranges are continuous**: A range like `8-18` means from 8AM to 6:59PM (inclusive of both start and end hours)
- **Weekday ranges**: `1-5` means Monday through Friday (Monday=1, Friday=5)
- **No overlapping schedules**: The validation system prevents overlapping schedules.

**Example schedules:**

```tf
# Business hours only (8AM-6:59PM, Mon-Fri)
schedule {
  cron = "* 8-18 * * 1-5"
  instances = 5
}

# 24/7 coverage with reduced capacity overnight and on weekends
schedule {
  cron = "* 8-18 * * 1-5"  # Business hours (8AM-6:59PM, Mon-Fri)
  instances = 10
}
schedule {
  cron = "* 19-23,0-7 * * 1,5"  # Evenings and nights (7PM-11:59PM, 12AM-7:59AM, Mon-Fri)
  instances = 2
}
schedule {
  cron = "* * * * 6,0"  # Weekends
  instances = 2
}

# Weekend support (10AM-4:59PM, Sat-Sun)
schedule {
  cron = "* 10-16 * * 6,0"
  instances = 1
}
```

### Template updates and the prebuilt workspace lifecycle

Prebuilt workspaces are not updated after they are provisioned.

When a template's active version is updated:

1. Prebuilt workspaces for old versions are automatically deleted.
1. New prebuilt workspaces are created for the active template version.
1. If dependencies change (e.g., an [AMI](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) update) without a template version change:
   - You can delete the existing prebuilt workspaces manually.
   - Coder will automatically create new prebuilt workspaces with the updated dependencies.

The system always maintains the desired number of prebuilt workspaces for the active template version.

<a id="invalidating-prebuilds"></a>

### Invalidate prebuilds

When external dependencies change without a template version update, you can invalidate presets to force their prebuilt workspaces to be recreated.

This is useful when:

- A base VM image or container image has been updated externally
- Infrastructure configuration has drifted from the desired state
- A monorepo cloned during the prebuild has fallen behind its origin
- You want to ensure prebuilt workspaces use the latest dependencies without publishing a new template version

To invalidate presets:

1. Navigate to **Templates** and select your template.
1. Go to the **Prebuilds** tab.
1. Select **Invalidate Prebuilds**.
1. Confirm the action in the dialog.

Once presets are invalidated, the **next reconciliation loop** run will delete the old prebuilt workspaces and create new ones to maintain the desired instance count.
The process typically completes within a few reconciliation cycles (the interval is controlled by `CODER_WORKSPACE_PREBUILDS_RECONCILIATION_INTERVAL`, which defaults to 1&nbsp;minute, or `1m0s`).

> [!NOTE]
> Preset invalidation only affects unclaimed prebuilt workspaces owned by the `prebuilds` system user.
> Workspaces that have already been claimed by users are not affected.
> The invalidation is not instantaneous and will take effect during the next reconciliation loop run.

## Administration and troubleshooting

<a id="managing-resource-quotas"></a>

### Manage resource quotas

To help prevent unexpected infrastructure costs, prebuilt workspaces can be used in conjunction with [resource quotas](../../users/quotas.md).
Because unclaimed prebuilt workspaces are owned by the `prebuilds` user, you can:

1. Configure quotas for any group that includes this user.
1. Set appropriate limits to balance prebuilt workspace availability with resource constraints.

When prebuilt workspaces are configured for an organization, Coder creates a group named `coderprebuiltworkspaces` (the **Prebuilt Workspaces** group) in that organization and adds the `prebuilds` user to it.
This group has a default quota allowance of 0, which you should adjust based on your needs:

- **Set a Quota Allowance** on the `coderprebuiltworkspaces` group to control how many prebuilt workspaces can be provisioned.
- **Monitor usage** to ensure the quota is appropriate for your desired number of prebuilt instances.
- **Adjust as needed** based on your template costs and desired prebuilt workspace pool size.

> [!NOTE]
> The `prebuilds` user is a system user, so it does not appear in the group's member list in the Coder dashboard or API, even though it is a member.

If a quota is exceeded, the prebuilt workspace will fail provisioning the same way other workspaces do.

<a id="managing-prebuild-provisioning-queues"></a>

### Manage prebuild provisioning queues

Prebuilt workspaces can overwhelm a Coder deployment, causing significant delays when users and template administrators create new workspaces or manage their templates. Fundamentally, this happens when provisioners are not able to meet the demand for provisioner jobs. Prebuilds contribute to provisioner demand by scheduling many jobs in bursts whenever templates are updated. The solution is to either increase the number of provisioners or decrease the number of requested prebuilt workspaces across the entire system.

To identify if prebuilt workspaces have overwhelmed the available provisioners in your Coder deployment, look for:

- Large or growing queue of prebuild-related jobs
- User workspace creation is slow
- Publishing a new template version is not reflected in the UI because the associated template import job has not yet finished

The troubleshooting steps below will help you assess and resolve this situation:

1) Pause prebuilt workspace reconciliation to stop the problem from getting worse
2) Check how many prebuild jobs are clogging your provisioner queue
3) Cancel excess prebuild jobs to free up provisioners for human users
4) Fix any problematic templates that are causing the issue
5) Resume prebuilt reconciliation once everything is back to normal

#### Pause prebuilds to limit potential impact

Run:

```sh
coder prebuilds pause
```

This prevents further pollution of your provisioner queues by stopping the prebuilt workspaces feature from scheduling new creation jobs. While the pause is in effect, no new prebuilt workspaces will be scheduled for any templates in any organizations across the entire Coder deployment.  Therefore, the command must be executed by a user with Owner level access. Existing prebuilt workspaces will remain in place.

**Important**: Remember to run `coder prebuilds resume` once all impact has been mitigated (see the last step in this section).

#### Assess prebuild queue impact

Next, run:

```sh
coder provisioner jobs list --status=pending --initiator=prebuilds
```

This will show a list of all pending jobs that have been enqueued by the prebuilt workspace system. The length of this list indicates whether prebuilt workspaces have overwhelmed your Coder deployment.

Human-initiated jobs have priority over pending prebuild jobs, but running prebuild jobs cannot be preempted. A long list of pending prebuild jobs increases the likelihood that all provisioners are already occupied when a user wants to create a workspace or import a new template version. This increases the likelihood that users will experience delays waiting for the next available provisioner.

#### Cancel pending prebuild jobs

Human-initiated jobs are prioritized above prebuild jobs in the provisioner queue. However, if no human-initiated jobs are queued when a provisioner becomes available, a prebuild job will occupy the provisioner. This can delay human-initiated jobs that arrive later, forcing them to wait for the next available provisioner.

To expedite fixing a broken template by ensuring maximum provisioner availability, cancel all pending prebuild jobs:

```sh
coder provisioner jobs list --status=pending --initiator=prebuilds --output json | jq -r '.[].id' | xargs -n1 -P2 -I{} coder provisioner jobs cancel {}
```

This will clear the provisioner queue of all jobs that were not initiated by a human being, which increases the probability that a provisioner will be available when the next human operator needs it. It does not cancel running provisioner jobs, so there may still be some delay in processing new provisioner jobs until a provisioner completes its current job.

At this stage, most prebuild related impact will have been mitigated. There may still be a bugged template version, but it will no longer pollute provisioner queues with prebuilt workspace jobs. If the latest version of a template is also broken for reasons unrelated to prebuilds, then users are able to create workspaces using a previous template version. Some running jobs may have been initiated by the prebuild system, but these cannot be cancelled without potentially orphaning resources that have already been deployed by Terraform. Depending on your deployment and template provisioning times, it might be best to upload a new template version and wait for it to be processed organically.

#### Cancel running prebuild provisioning jobs (Optional)

If you need to expedite the processing of human-related jobs at the cost of some infrastructure housekeeping, you can run:

```sh
coder provisioner jobs list --status=running --initiator=prebuilds --output json | jq -r '.[].id' | xargs -n1 -P2 -I{} coder provisioner jobs cancel {}
```

This should be done as a last resort. It will cancel running prebuild jobs (orphaning any resources that have already been deployed) and immediately make room for human-initiated jobs. Orphaned infrastructure will need to be manually cleaned up by a human operator. The process to identify and clear these orphaned resources will likely require administrative access to the infrastructure that hosts Coder workspaces. Furthermore, the ability to identify such orphaned resources will depend on metadata that should be included in the workspace template.

Once the provisioner queue has been cleared and all templates have been fixed, resume prebuild reconciliation by running:

#### Resume prebuild reconciliation

```sh
coder prebuilds resume
```

This re-enables the prebuilt workspaces feature and allows the reconciliation loop to resume normal operation. The system will begin creating new prebuilt workspaces according to your template configurations.

### Template configuration best practices

<a id="preventing-resource-replacement"></a>

#### Prevent resource replacement

When a prebuilt workspace is claimed, another `terraform apply` run occurs with new values for the workspace owner and name.

This can cause issues in the following scenario:

1. The workspace is initially created with values from the `prebuilds` user and a random name.
1. After claiming, various workspace properties change (ownership, name, and potentially other values), which Terraform sees as configuration drift.
1. If these values are used in immutable fields, Terraform will destroy and recreate the resource, eliminating the benefit of prebuilds.

For example, when these values are used in immutable fields like the AWS instance `user_data`, you'll see resource replacement during claiming:

![Resource replacement notification](../../../images/admin/templates/extend-templates/prebuilt/replacement-notification.png)

To prevent this, add a `lifecycle` block with `ignore_changes`:

```tf
resource "docker_container" "workspace" {
  lifecycle {
    ignore_changes = [env, image] # include all fields which caused drift
  }

  count = data.coder_workspace.me.start_count
  name  = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
  ...
}
```

Limit the scope of `ignore_changes` to include only the fields specified in the notification.
If you include too many fields, Terraform might ignore changes that wouldn't otherwise cause drift.

Learn more about `ignore_changes` in the [Terraform documentation](https://developer.hashicorp.com/terraform/language/meta-arguments#lifecycle).

_A note on "immutable" attributes: Terraform providers may specify `ForceNew` on their resources' attributes. Any change
to these attributes require the replacement (destruction and recreation) of the managed resource instance, rather than an in-place update.
For example, the [`ami`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance#ami-1) attribute on the `aws_instance` resource
has [`ForceNew`](https://github.com/hashicorp/terraform-provider-aws/blob/main/internal/service/ec2/ec2_instance.go#L75-L81) set,
since the AMI cannot be changed in-place._

<a id="preventing-prebuild-queue-contention-recommended"></a>

### Prevent prebuild queue contention (recommended)

The section [Manage prebuild provisioning queues](#manage-prebuild-provisioning-queues) covers how to recover when prebuilds have already overwhelmed the provisioner queue.
This section outlines a **best-practice configuration** to prevent that situation by isolating prebuild jobs to a dedicated provisioner pool.
This setup is optional and requires minor template changes.

Coder supports [external provisioners and provisioner tags](../../../install/operate/provisioners/index.md), which allows you to route jobs to provisioners with matching tags.
By creating external provisioners with a special tag (e.g., `is_prebuild=true`) and updating the template to conditionally add that tag for prebuild jobs,
all prebuild work is handled by the prebuild pool.
This keeps other provisioners available to handle user-initiated jobs.

#### Setup

1. Create a provisioner key with a prebuild tag (e.g., `is_prebuild=true`).
    Provisioner keys are org-scoped and their tags are inferred automatically by provisioner daemons that use the key.
    **Note:** `coder_workspace_tags` are cumulative, so if your template already defines provisioner tags, you will need to create the provisioner key with the same tags plus the `is_prebuild=true` tag so that prebuild jobs correctly match the dedicated prebuild pool.
    See [Scoped Key](../../../install/operate/provisioners/index.md#scoped-key-recommended) for instructions on how to create a provisioner key.

1. Deploy a separate provisioner pool using that key (for example, via the [Helm coder-provisioner chart](https://github.com/coder/coder/pkgs/container/chart%2Fcoder-provisioner)).
    Daemons in this pool will only execute jobs that include all of the tags specified in their provisioner key.
    See [External provisioners](../../../install/operate/provisioners/index.md) for environment-specific deployment examples.

1. Update the template to conditionally add the prebuild tag for prebuild jobs.

    ```tf
    data "coder_workspace_tags" "prebuilds" {
      count = data.coder_workspace_owner.me.name == "prebuilds" ? 1 : 0
      tags = {
        "is_prebuild" = "true"
      }
    }
    ```

Prebuild workspaces are a special type of workspace owned by the system user `prebuilds`.
The value `data.coder_workspace_owner.me.name` returns the name of the workspace owner, for prebuild workspaces, this value is `"prebuilds"`.
Because the condition evaluates based on the workspace owner, provisioning or deprovisioning prebuilds automatically applies the prebuild tag, whereas regular jobs (like workspace creation or template import) do not.

> [!NOTE]
> The prebuild provisioner pool can still accept non-prebuild jobs.
> To achieve a fully isolated setup, add an additional tag (`is_prebuild=false`) to your standard provisioners, ensuring a clean separation between prebuild and non-prebuild workloads.
> See [Provisioner Tags](../../../install/operate/provisioners/index.md#provisioner-tags) for further details.

#### Validation

To confirm that prebuild jobs are correctly routed to the new provisioner pool, use the Provisioner Jobs dashboard or the [`coder provisioner jobs list`](../../../reference/cli/provisioner/jobs/list.md) CLI command to inspect job metadata and tags.
Follow these steps:

1. Publish the new template version.

1. Validate the status of the prebuild provisioners.
    Check the Provisioners page in the Coder dashboard or run the [`coder provisioner list`](../../../reference/cli/provisioner/list.md) CLI command to ensure all prebuild provisioners are up to date and the tags are properly set.

1. Wait for the prebuilds reconciliation loop to run.
    The loop frequency is controlled by the configuration value [`CODER_WORKSPACE_PREBUILDS_RECONCILIATION_INTERVAL`](../../../reference/cli/server/index.md#--workspace-prebuilds-reconciliation-interval).
    When the loop runs, it will provision prebuilds for the new template version and deprovision prebuilds for the previous version.
    Both provisioning and deprovisioning jobs for prebuilds should display the tag `is_prebuild=true`.

1. Create a new workspace from a preset.
    Whether the preset uses a prebuild pool or not, the resulting job should not include the `is_prebuild=true` tag.
    This confirms that only prebuild-related jobs are routed to the dedicated prebuild provisioner pool.

### Monitoring and observability

#### Available metrics

Coder provides several metrics to monitor your prebuilt workspaces:

- `coderd_prebuilt_workspaces_created_total` (counter): Total number of prebuilt workspaces created to meet the desired instance count.
- `coderd_prebuilt_workspaces_failed_total` (counter): Total number of prebuilt workspaces that failed to build.
- `coderd_prebuilt_workspaces_claimed_total` (counter): Total number of prebuilt workspaces claimed by users.
- `coderd_prebuilt_workspaces_desired` (gauge): Target number of prebuilt workspaces that should be available.
- `coderd_prebuilt_workspaces_running` (gauge): Current number of prebuilt workspaces in a `running` state.
- `coderd_prebuilt_workspaces_eligible` (gauge): Current number of prebuilt workspaces eligible to be claimed.
- `coderd_prebuilt_workspace_claim_duration_seconds` ([_native histogram_](https://prometheus.io/docs/specs/native_histograms) support): Time to claim a prebuilt workspace from the prebuild pool.

#### Logs

Search for `coderd.prebuilds:` in your logs to track the reconciliation loop's behavior.

These logs provide information about:

1. Creation and deletion attempts for prebuilt workspaces.
1. Backoff events after failed builds.
1. Claiming operations.

---

# Icons

Source: https://coder.com/docs/admin/templates/extending-templates/icons

Coder uses icons in several places, including ones that can be configured
throughout the app, or specified in your Terraform. They're specified by a URL,
which can be to an image hosted on a CDN of your own, or one of the icons that
come bundled with your Coder deployment.

- **Template Icons**:

  - Make templates and workspaces visually recognizable with a relevant or
    memorable icon

- [**Terraform**](https://registry.terraform.io/providers/coder/coder/latest/docs):

  - [`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app#icon-1)
  - [`coder_parameter`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter#icon-1)
    and
    [`option`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/parameter#nested-schema-for-option)
    blocks
  - [`coder_script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/script#icon-1)
  - [`coder_metadata`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/metadata#icon-1)

  These can all be configured to use an icon by setting the `icon` field.

  ```tf
  data "coder_parameter" "my_parameter" {
    icon = "/icon/coder.svg"

    option {
      icon = "/emojis/1f3f3-fe0f-200d-26a7-fe0f.png"
    }
  }
  ```

- [**Authentication Providers**](../../external-auth/index.md):

  - Use icons for external authentication providers to make them recognizable.
    You can set an icon for each provider by setting the
    `CODER_EXTERNAL_AUTH_X_ICON` environment variable, where `X` is the number
    of the provider.

    ```dotenv
    CODER_EXTERNAL_AUTH_0_ICON=/icon/github.svg
    CODER_EXTERNAL_AUTH_1_ICON=/icon/google.svg
    ```

- [**Support Links**](../../setup/appearance.md#support-links):

  - Use icons for support links to make them recognizable. You can set the
    `icon` field for each link in `CODER_SUPPORT_LINKS` array.

## Bundled icons

Coder is distributed with a bundle of icons for popular cloud providers and
programming languages. You can see all of the icons (or suggest new ones) in our
repository on
[GitHub](../../../../site/static/icon).

You can also view the entire list, with search and previews, by navigating to
`/icons` on your Coder deployment (for example,
`https://coder.example.com/icons`). This can be particularly useful in airgapped
deployments.

![The icon gallery](../../../images/icons-gallery.png)

## External icons

You can use any image served over HTTPS as an icon, by specifying the full URL
of the image. We recommend that you use a CDN that you control, but it can be
served from any source that you trust.

You can also embed an image by using data: URLs.

- Only the https: and data: protocols are supported in icon URLs (not http:)

- Be careful when using images hosted by someone else; they might disappear or
  change!

- Be careful when using data: URLs. They can get rather large, and can
  negatively impact loading times for pages and queries they appear in. Only use
  them for very small icons that compress well.

---

# Resource Metadata

Source: https://coder.com/docs/admin/templates/extending-templates/resource-metadata

Expose key workspace information to your users with
[`coder_metadata`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/metadata)
resources in your template code.

You can use `coder_metadata` to show Terraform resource attributes like these:

- Compute resources
- IP addresses
- [Secrets](../../security/secrets.md#display-secrets)
- Important file paths

![ui](../../../images/admin/templates/coder-metadata-ui.png)

> [!NOTE]
> Coder automatically generates the <code>type</code> metadata.

You can also present automatically updating, dynamic values with
[agent metadata](./agent-metadata.md).

## Example

Expose the disk size, deployment name, and persistent directory in a Kubernetes
template with:

```tf
resource "kubernetes_persistent_volume_claim" "root" {
    ...
}

resource "kubernetes_deployment" "coder" {
  # My deployment is ephemeral
  count = data.coder_workspace.me.start_count
  ...
}

resource "coder_metadata" "pvc" {
  resource_id = kubernetes_persistent_volume_claim.root.id
  item {
    key = "size"
    value = kubernetes_persistent_volume_claim.root.spec[0].resources[0].requests.storage
  }
  item {
    key = "dir"
    value = "/home/coder"
  }
}

resource "coder_metadata" "deployment" {
  count = data.coder_workspace.me.start_count
  resource_id = kubernetes_deployment.coder[0].id
  item {
    key = "name"
    value = kubernetes_deployment.coder[0].metadata[0].name
  }
}
```

<a id="hiding-resources-in-the-dashboard"></a>

## Hide resources in the dashboard

Some resources don't need to be exposed in the dashboard's UI. This helps keep
the workspace view clean for developers. To hide a resource, use the `hide`
attribute:

```tf
resource "coder_metadata" "hide_serviceaccount" {
  count = data.coder_workspace.me.start_count
  resource_id = kubernetes_service_account.user_data.id
  hide = true
  item {
    key = "name"
    value = kubernetes_deployment.coder[0].metadata[0].name
  }
}
```

<a id="using-a-custom-resource-icon"></a>

## Use a custom resource icon

To use custom icons for your resource metadata, use the `icon` attribute. It
must be a valid path or URL.

```tf
resource "coder_metadata" "resource_with_icon" {
  count = data.coder_workspace.me.start_count
  resource_id = kubernetes_service_account.user_data.id
  icon = "/icon/database.svg"
  item {
    key = "name"
    value = kubernetes_deployment.coder[0].metadata[0].name
  }
}
```

To make it easier for you to customize your resource we added some built-in
icons:

- Folder `/icon/folder.svg`
- Memory `/icon/memory.svg`
- Image `/icon/image.svg`
- Widgets `/icon/widgets.svg`
- Database `/icon/database.svg`

We also have other icons related to the IDEs. You can see more information on
how to use the builtin icons [here](./icons.md).

## Up next

- [Secrets](../../security/secrets.md)
- [Agent metadata](./agent-metadata.md)

---

# Resource monitoring

Source: https://coder.com/docs/admin/templates/extending-templates/resource-monitoring

Use the
[`resources_monitoring`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#resources_monitoring-1)
block on the
[`coder_agent`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent)
resource in our Terraform provider to monitor out of memory (OOM) and out of
disk (OOD) errors and alert users when they overutilize memory and disk.

This can help prevent agent disconnects due to OOM/OOD issues.

You can specify one or more volumes to monitor for OOD alerts.
OOM alerts are reported per-agent.

## Prerequisites

Notifications are sent through SMTP.
Configure Coder to [use an SMTP server](../../monitoring/notifications/index.md#smtp-email).

## Example

Add the following example to the template's `main.tf`.
Change the `90`, `80`, and `95` to a threshold that's more appropriate for your
deployment:

```tf
resource "coder_agent" "main" {
  arch = data.coder_provisioner.dev.arch
  os   = data.coder_provisioner.dev.os
  resources_monitoring {
    memory {
      enabled   = true
      threshold = 90
    }
    volume {
      path      = "/volume1"
      enabled   = true
      threshold = 80
    }
    volume {
      path      = "/volume2"
      enabled   = true
      threshold = 95
    }
  }
}
```

---

# UI resource ordering

Source: https://coder.com/docs/admin/templates/extending-templates/resource-ordering

In Coder templates, managing the order of UI elements is crucial for a seamless
user experience. This page outlines how resources can be aligned using the
`order` Terraform property or inherit the natural order from the file.

The resource with the lower `order` is presented before the one with greater
value. A missing `order` property defaults to 0. If two resources have the same
`order` property, the resources will be ordered by property `name` (or `key`).

<a id="using-order-property"></a>

## Use the "order" property

### Coder parameters

The `order` property of `coder_parameter` resource allows specifying the order
of parameters in UI forms. In the below example, `project_id` will appear
_before_ `account_id`:

```tf
data "coder_parameter" "project_id" {
  name         = "project_id"
  display_name = "Project ID"
  description  = "Specify cloud provider project ID."
  order = 2
}

data "coder_parameter" "account_id" {
  name         = "account_id"
  display_name = "Account ID"
  description  = "Specify cloud provider account ID."
  order = 1
}
```

### Agents

Agent resources within the UI left pane are sorted based on the `order`
property, followed by `name`, ensuring a consistent and intuitive arrangement.

```tf
resource "coder_agent" "primary" {
  ...

  order = 1
}

resource "coder_agent" "secondary" {
  ...

  order = 2
}
```

The agent with the lowest order is presented at the top in the workspace view.

### Agent metadata

The `coder_agent` exposes metadata to present operational metrics in the UI.
Metrics defined with Terraform `metadata` blocks can be ordered using additional
`order` property; otherwise, they are sorted by `key`.

```tf
resource "coder_agent" "main" {
  ...

  metadata {
    display_name = "CPU Usage"
    key          = "cpu_usage"
    script       = "coder stat cpu"
    interval     = 10
    timeout      = 1
    order        = 1
  }
  metadata {
    display_name = "CPU Usage (Host)"
    key          = "cpu_usage_host"
    script       = "coder stat cpu --host"
    interval     = 10
    timeout      = 1
    order        = 2
  }
  metadata {
    display_name = "RAM Usage"
    key          = "ram_usage"
    script       = "coder stat mem"
    interval     = 10
    timeout      = 1
    order        = 1
  }
  metadata {
    display_name = "RAM Usage (Host)"
    key          = "ram_usage_host"
    script       = "coder stat mem --host"
    interval     = 10
    timeout      = 1
    order        = 2
  }
}
```

### Applications

Similarly to Coder agents, `coder_app` resources incorporate the `order`
property to organize button apps in the app bar within a `coder_agent` in the
workspace view.

Only template defined applications can be arranged. _VS Code_ or _Terminal_
buttons are static.

```tf
resource "coder_app" "code-server" {
  agent_id     = coder_agent.main.id
  slug         = "code-server"
  display_name = "code-server"
  ...

  order = 2
}

resource "coder_app" "filebrowser" {
  agent_id     = coder_agent.main.id
  display_name = "File Browser"
  slug         = "filebrowser"
  ...

  order = 1
}
```

## Inherit order from file

### Coder parameter options

The options for Coder parameters maintain the same order as in the file
structure. This simplifies management and ensures consistency between
configuration files and UI presentation.

```tf
data "coder_parameter" "database_region" {
  name         = "database_region"
  display_name = "Database Region"

  icon        = "/icon/database.svg"
  description = "These are options."
  mutable     = true
  default     = "us-east1-a"

  // The order of options is stable and inherited from .tf file.
  option {
    name        = "US Central"
    description = "Select for central!"
    value       = "us-central1-a"
  }
  option {
    name        = "US East"
    description = "Select for east!"
    value       = "us-east1-a"
  }
  ...
}
```

### Coder metadata items

In cases where multiple item properties exist, the order is inherited from the
file, facilitating seamless integration between a Coder template and UI
presentation.

```tf
resource "coder_metadata" "attached_volumes" {
  resource_id = docker_image.main.id

  // Items will be presented in the UI in the following order.
  item {
    key   = "disk-a"
    value = "60 GiB"
  }
  item {
    key   = "disk-b"
    value = "128 GiB"
  }
}
```

---

# Resource persistence

Source: https://coder.com/docs/admin/templates/extending-templates/resource-persistence

By default, all Coder resources are persistent, but production templates
**must** use the practices laid out in this document to prevent accidental
deletion.

Coder templates have full control over workspace ephemerality. In a completely
ephemeral workspace, there are zero resources in the Off state. In a completely
persistent workspace, there is no difference between the Off and On states.

The needs of most workspaces fall somewhere in the middle, persisting user data
like filesystem volumes, but deleting expensive, reproducible resources such as
compute instances.

<a id="disabling-persistence"></a>

## Turn off persistence

The Terraform
[`coder_workspace` data source](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace)
exposes the `start_count = [0 | 1]` attribute. To make a resource ephemeral, you
can assign the `start_count` attribute to resource's
[`count`](https://developer.hashicorp.com/terraform/language/meta-arguments/count)
meta-argument.

In this example, Coder will provision or tear down the `docker_container`
resource:

```tf
data "coder_workspace" "me" {
}

resource "docker_container" "workspace" {
  # When `start_count` is 0, `count` is 0, so no `docker_container` is created.
  count = data.coder_workspace.me.start_count # 0 (stopped), 1 (started)
  # ... other config
}
```

## ⚠️ Persistence pitfalls

Take this example resource:

```tf
data "coder_workspace" "me" {
}

resource "docker_volume" "home_volume" {
  name = "coder-${data.coder_workspace.me.owner}-home"
}
```

Because we depend on `coder_workspace.me.owner`, if the owner changes their
username, Terraform will recreate the volume (wiping its data!) the next time
that Coder starts the workspace.

✅ To prevent this, use immutable IDs:

- `coder_workspace.me.owner_id`
- `coder_workspace.me.id`

⚠️ Avoid mutable IDs:

- `coder_workspace.me.name`
- `coder_workspace.me.owner`

Workspace renaming is disabled by default to help prevent this kind of
destruction, but a template admin can enable it. Refer to
[Workspace renaming](../managing-templates/index.md#workspace-renaming).

```tf
data "coder_workspace" "me" {
}

resource "docker_volume" "home_volume" {
  # This volume will survive until the Workspace is deleted or the template
  # admin changes this resource block.
  name = "coder-${data.coder_workspace.id}-home"
}
```

## 🛡 Bulletproofing

Even if your persistent resource depends exclusively on immutable IDs, a change
to the `name` format or other attributes would cause Terraform to rebuild the
resource.

You can prevent Terraform from recreating a resource under any circumstance by
setting the
[`ignore_changes = all` directive in the `lifecycle` block](https://developer.hashicorp.com/terraform/language/meta-arguments/lifecycle#ignore_changes).

```tf
data "coder_workspace" "me" {
}

resource "docker_volume" "home_volume" {
  # This resource will survive until either the entire block is deleted
  # or the workspace is.
  name = "coder-${data.coder_workspace.me.id}-home"
  lifecycle {
    ignore_changes = all
  }
}
```

---

# Environment variables

Source: https://coder.com/docs/admin/templates/extending-templates/environment-variables

Use the
[`coder_env`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/env)
resource to inject environment variables into your workspace agents. This is
useful for configuring tools, setting paths, and passing configuration to
development environments.

## Basic usage

```tf
resource "coder_agent" "dev" {
  os   = "linux"
  arch = "amd64"
}

resource "coder_env" "go_path" {
  agent_id = coder_agent.dev.id
  name     = "GOPATH"
  value    = "/home/coder/go"
}
```

Each `coder_env` resource sets a single environment variable on the specified
agent. You can define multiple `coder_env` resources targeting the same agent.

## Merge strategies

When multiple `coder_env` resources define the same variable name, use the
`merge_strategy` attribute to control how values are combined:

| Strategy              | Behavior                                            |
|-----------------------|-----------------------------------------------------|
| `replace` _(default)_ | Last value wins. Backward compatible.               |
| `append`              | Appends to the existing value with `:` separator.   |
| `prepend`             | Prepends to the existing value with `:` separator.  |
| `error`               | Fails the build if the variable is already defined. |

The `append` and `prepend` strategies use `:` as a separator, which matches
the convention for `PATH`-style variables on Unix systems.

### Merges and the host environment

`merge_strategy` only combines values across `coder_env` resources in the same template.
It does not know about the value already set by the workspace's image or host, such as the base `PATH`.
An `append` or `prepend` builds its value from `coder_env` resources alone, and that value replaces whatever the host had set for that variable.

To extend a variable that the host already sets, reference it directly in one of the values (for example, `$PATH`), so the agent expands it against the real environment at startup.
Only one resource in the chain needs the reference; the rest can use plain values.
The next example covers this.

### Example: Appending to PATH

Multiple `coder_env` resources can each add directories to `PATH`.
Reference `$PATH` in one of them to keep the host's original directories:

```tf
resource "coder_agent" "dev" {
  os   = "linux"
  arch = "amd64"
}

resource "coder_env" "path_cuda" {
  agent_id       = coder_agent.dev.id
  name           = "PATH"
  value          = "$PATH:/usr/local/cuda/bin"
  merge_strategy = "append"
}

resource "coder_env" "path_go" {
  agent_id       = coder_agent.dev.id
  name           = "PATH"
  value          = "/usr/local/go/bin"
  merge_strategy = "append"
}

resource "coder_env" "path_rust_cargo" {
  agent_id       = coder_agent.dev.id
  name           = "PATH"
  value          = "/usr/local/cargo/bin"
  merge_strategy = "append"
}
```

This produces `PATH` with the host's original value, followed by `/usr/local/cuda/bin:/usr/local/go/bin:/usr/local/cargo/bin`.

### Example: Preventing duplicates

Use `error` to catch accidental duplicate definitions:

```tf
resource "coder_env" "editor" {
  agent_id       = coder_agent.dev.id
  name           = "EDITOR"
  value          = "vim"
  merge_strategy = "error"
}
```

If another `coder_env` resource also sets `EDITOR`, the build fails with
a clear error message.

## Ordering

When multiple `coder_env` resources append or prepend to the same variable,
they are processed in alphabetical order by their
[Terraform resource address](https://developer.hashicorp.com/terraform/cli/state/resource-addressing).
In the previous `PATH` example, `coder_env.path_cuda` is processed first, then `coder_env.path_go`, then `coder_env.path_rust_cargo`, because that is their alphabetical order.
This is why only one resource in the chain needs the `$PATH` reference: the merged value is built as one string before it's expanded, so the reference works no matter where in the chain it appears.

## Agent env override

The `env` block inside a `coder_agent` resource always takes final precedence
over any `coder_env` resources. If both define the same variable, the
`coder_agent` value wins regardless of `merge_strategy`. This override happens
after `coder_env` resources are merged, so `merge_strategy = "error"` does not
trigger when the conflict is with the agent's `env` block — only when two
`coder_env` resources define the same key:

```tf
resource "coder_agent" "dev" {
  os   = "linux"
  arch = "amd64"
  env = {
    PATH = "/usr/local/bin:/usr/bin:/bin"
  }
}

# This value is ignored because coder_agent.dev.env sets PATH directly.
resource "coder_env" "extra_path" {
  agent_id       = coder_agent.dev.id
  name           = "PATH"
  value          = "/home/coder/bin"
  merge_strategy = "append"
}
```

See the
[Coder Terraform provider documentation](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/env)
for the complete `coder_env` reference.

---

# Terraform template-wide variables

Source: https://coder.com/docs/admin/templates/extending-templates/variables

In Coder, Terraform templates offer extensive flexibility through template-wide
variables. These variables, managed by template authors, facilitate the
construction of customizable templates. Unlike parameters, which are primarily
for workspace customization, template variables remain under the control of the
template author, ensuring workspace users cannot modify them.

```tf
variable "CLOUD_API_KEY" {
  type        = string
  description = "API key for the service"
  default     = "1234567890"
  sensitive   = true
}
```

Given that variables are a
[fundamental concept in Terraform](https://developer.hashicorp.com/terraform/language/values/variables),
Coder endeavors to fully support them. Native support includes `string`,
`number`, and `bool` formats. However, other types such as `list(string)` or
`map(any)` will default to being treated as strings.

## Default value

Upon adding a template variable, it's mandatory to provide a value during the
first push. At this stage, the template administrator faces two choices:

1. _No `default` property_: opt not to define a default property. Instead,
   utilize the `--var name=value` command-line argument during the push to
   supply the variable's value.
2. _Define `default` property_: set a default property for the template
   variable. If the administrator doesn't input a value via CLI, Coder
   automatically uses this default during the push.

After the initial push, variables are stored in the database table, associated
with the specific template version. They can be conveniently managed via
_Template Settings_ without requiring an extra push.

### Resolved values vs. default values

It's crucial to note that Coder templates operate based on resolved values
during a push, rather than default values. This ensures that default values do
not inadvertently override the configured variable settings during the push
process.

This approach caters to users who prefer to avoid accidental overrides of their
variable settings with default values during pushes, thereby enhancing control
and predictability.

If you encounter a situation where you need to override template settings for
variables, you can employ a straightforward solution:

1. Create a `terraform.tfvars` file in the template directory:

   ```tf
   coder_image = newimage:tag
   ```

1. Push the new template revision using Coder CLI:

   ```sh
   coder templates push my-template -y # no need to use --var
   ```

This file serves as a mechanism to override the template settings for variables.
It can be stored in the repository for easy access and reference. Coder CLI
automatically detects it and loads variable values.

## Input options

When working with Terraform configurations in Coder, you have several options
for providing values to variables using the Coder CLI:

1. _Manual input in CLI_: You can manually input values for Terraform variables
   directly in the CLI during the deployment process.
1. _Web UI_: You can set or edit variable values under **Variables** in the
   template's settings.
1. _Command-line argument_: Utilize the `--var name=value` command-line argument
   to specify variable values inline as key-value pairs.
1. _Variables file selection_: Alternatively, you can use a variables file
   selected via the `--variables-file values.yml` command-line argument. This
   approach is particularly useful when dealing with multiple variables or to
   avoid manual input of numerous values. Variables files can be versioned for
   better traceability and management, and it enhances reproducibility.

Here's an example of a YAML-formatted variables file, `values.yml`:

```yaml
region: us-east-1
bucket_name: magic
zone_types: '{"us-east-1":"US East", "eu-west-1": "EU West"}'
cpu: 1
```

In this sample file:

- `region`, `bucket_name`, `zone_types`, and `cpu` are Terraform variable names.
- Corresponding values are provided for each variable.
- The `zone_types` variable demonstrates how to provide a JSON-formatted string
  as a value in YAML.

## Terraform .tfvars files

In Terraform, `.tfvars` files provide a convenient means to define variable
values for a project in a reusable manner. These files, ending with either
`.tfvars` or `.tfvars.json`, streamline the process of setting numerous
variables.

By utilizing `.tfvars` files, you can efficiently manage and organize variable
values for your Terraform projects. This approach offers several advantages:

- Clarity and consistency: Centralize variable definitions in dedicated files,
  enhancing clarity, instead of input values on template push.
- Ease of maintenance: Modify variable values in a single location under version
  control, simplifying maintenance and updates.

Coder automatically loads variable definition files following a specific order,
providing flexibility and control over variable configuration. The loading
sequence is as follows:

1. `terraform.tfvars`: This file contains variable values and is loaded first.
2. `terraform.tfvars.json`: If present, this JSON-formatted file is loaded after
   `terraform.tfvars`.
3. `\*.auto.tfvars`: Files matching this pattern are loaded next, ordered
   alphabetically.
4. `\*.auto.tfvars.json`: JSON-formatted files matching this pattern are loaded
   last.

---

# Reuse template code

Source: https://coder.com/docs/admin/templates/extending-templates/modules

To reuse code across different Coder templates, such as common scripts or
resource definitions, we suggest using
[Terraform Modules](https://developer.hashicorp.com/terraform/language/modules).

You can store these modules externally from your Coder deployment, like in a git
repository or a Terraform registry. This example shows how to reference a module
from your template:

```tf
data "coder_workspace" "me" {}

module "coder-base" {
  source = "github.com/my-organization/coder-base"

  # Modules take in variables and can provision infrastructure
  vpc_name            = "devex-3"
  subnet_tags         = { "name": data.coder_workspace.me.name }
  code_server_version = 4.14.1
}

resource "coder_agent" "dev" {
  # Modules can provide outputs, such as helper scripts
  startup_script=<<EOF
  #!/bin/sh
  ${module.coder-base.code_server_install_command}
  EOF
}
```

Learn more about
[creating modules](https://developer.hashicorp.com/terraform/language/modules)
and
[module sources](https://developer.hashicorp.com/terraform/language/modules/sources)
in the Terraform documentation.

## Coder modules

Coder publishes plenty of modules that can be used to simplify some common tasks
across templates. Some of the modules we publish are,

1. [`code-server`](https://registry.coder.com/modules/coder/code-server) and
   [`vscode-web`](https://registry.coder.com/modules/coder/vscode-web)
2. [`git-clone`](https://registry.coder.com/modules/coder/git-clone)
3. [`dotfiles`](https://registry.coder.com/modules/coder/dotfiles)
4. [`jetbrains`](https://registry.coder.com/modules/coder/jetbrains)
5. [`jfrog-oauth`](https://registry.coder.com/modules/coder/jfrog-oauth) and
   [`jfrog-token`](https://registry.coder.com/modules/coder/jfrog-token)
6. [`vault-github`](https://registry.coder.com/modules/coder/vault-github)

For a full list of available modules please check
[Coder module registry](https://registry.coder.com/modules).

## Module caching

Module caching is enabled by default for all templates. When you publish a
new template version, Coder runs `terraform init` to resolve every module the
template references, then archives the resulting `.terraform/modules`
directory and stores it alongside that template version. On every subsequent
workspace build, Coder provisioners reuse this cached archive instead of
re-fetching modules from their original sources (a git repository, the Coder
registry, or another Terraform registry). This avoids redundant network and
disk I/O on each build and prevents build failures caused by a module source
being slow or temporarily unavailable.

Coder limits cached module archives to 20&nbsp;MB per template version.
If your modules exceed this limit, some are skipped and unavailable for [Dynamic Parameters](./dynamic-parameters.md#module-not-loaded-errors-when-using-dynamic-parameters) evaluation, though builds still fetch the skipped modules directly.
Template versions published before Coder started archiving modules have no cache at all, which produces the same ["Module not loaded"](./dynamic-parameters.md#module-not-loaded-errors-when-using-dynamic-parameters) warnings for every module in the workspace creation form; publishing a new template version fixes this.

To force Coder to re-download modules on every workspace build instead of
using the cached archive, select **Disable Terraform module caching** in a
template's **Settings** > **General** page, or set `disable_module_cache` to
`true` with the [templates API](../../../reference/api/templates.md#update-template-settings-by-id).

> [!WARNING]
> Disabling module caching makes workspace builds slower and less
> predictable, since Terraform re-resolves and downloads every module on each
> build. This isn't recommended for production templates.

## Offline installations

In offline and restricted deployments, there are three ways to fetch modules.

1. Artifactory Remote Terraform Repository (Recommended)
2. Artifactory Local Repository (manual publishing)
3. Private git repository

### Artifactory Remote Terraform Repository (Recommended)

Configure Artifactory as a **Remote Terraform Repository** that proxies and
caches the Coder registry. This approach provides automatic updates and
requires no manual synchronization.

See [Mirror the Coder Registry with JFrog Artifactory](../../../install/prepare/registry-mirror.md)
for complete setup instructions.

### Artifactory Local Repository

Air-gapped users can clone the [coder/registry](https://github.com/coder/registry/)
repo and publish a
[local terraform module repository](https://jfrog.com/help/r/jfrog-artifactory-documentation/terraform-opentofu-and-terraform-backend-repositories)
to resolve modules via [Artifactory](https://jfrog.com/artifactory/).

1. Create a local-terraform-repository with name `coder-modules-local`
1. Create a virtual repository with name `tf`
1. Follow the below instructions to publish coder modules to Artifactory

   ```sh
   git clone https://github.com/coder/registry
   cd registry/registry/coder/modules
   jf tfc
   jf tf p --namespace="coder" --provider="coder" --tag="1.0.0"
   ```

1. Generate a token with access to the `tf` repo and set an `ENV` variable
   `TF_TOKEN_example.jfrog.io="XXXXXXXXXXXXXXX"` on the Coder provisioner.
1. Create a file `.terraformrc` with following content and mount at
   `/home/coder/.terraformrc` within the Coder provisioner.

   ```tf
   provider_installation {
     direct {
         exclude = ["registry.terraform.io/*/*"]
     }
     network_mirror {
         url = "https://example.jfrog.io/artifactory/api/terraform/tf/providers/"
     }
   }
   ```

1. Update module source as:

   ```tf
   module "module-name" {
     source = "https://example.jfrog.io/tf__coder/module-name/coder"
     version = "1.0.0"
     agent_id = coder_agent.example.id
     ...
   }
   ```

   Replace `example.jfrog.io` with your Artifactory URL

Based on the instructions
[here](https://jfrog.com/blog/tour-terraform-registries-in-artifactory/).

#### Example template

We have an example template
[here](../../../../examples/jfrog/remote/main.tf)
that uses our
[JFrog Docker](../../../../examples/jfrog/docker/main.tf)
template as the underlying module.

### Private git repository

If you are importing a module from a private git repository, the control plane or
[provisioner](../../../install/operate/provisioners/index.md) needs git credentials. Since this token
will only be used for cloning your repositories with modules, it is best to
create a token with access limited to the repository and no extra permissions.
In GitHub, you can generate a
[fine-grained token](https://docs.github.com/en/rest/overview/permissions-required-for-fine-grained-personal-access-tokens?apiVersion=2022-11-28)
with read only access to the necessary repos.

If you are running Coder on a VM, make sure that you have `git` installed and
the `coder` user has access to the following files:

```sh
# /home/coder/.gitconfig
[credential]
  helper = store
```

```sh
# /home/coder/.git-credentials

# GitHub example:
https://your-github-username:your-github-pat@github.com
```

If you are running Coder on Docker or Kubernetes, `git` is pre-installed in the
Coder image. However, you still need to mount credentials. This can be done via
a Docker volume mount or Kubernetes secrets.

#### Pass git credentials in Kubernetes

First, create a `.gitconfig` and `.git-credentials` file on your local machine.
You might want to do this in a temporary directory to avoid conflicting with
your own git credentials.

Next, create the secret in Kubernetes. Be sure to do this in the same namespace
that Coder is installed in.

```sh
export NAMESPACE=coder
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: git-secrets
  namespace: $NAMESPACE
type: Opaque
data:
  .gitconfig: $(cat .gitconfig | base64 | tr -d '\n')
  .git-credentials: $(cat .git-credentials | base64 | tr -d '\n')
EOF
```

Then, modify Coder's Helm values to mount the secret.

```yaml
coder:
  volumes:
    - name: git-secrets
      secret:
        secretName: git-secrets
  volumeMounts:
    - name: git-secrets
      mountPath: "/home/coder/.gitconfig"
      subPath: .gitconfig
      readOnly: true
    - name: git-secrets
      mountPath: "/home/coder/.git-credentials"
      subPath: .git-credentials
      readOnly: true
```

### Next steps

- JFrog's
  [Terraform Registry support](https://jfrog.com/help/r/jfrog-artifactory-documentation/terraform-opentofu-and-terraform-backend-repositories)
- [Configuring the JFrog toolchain inside a workspace](../../integrations/jfrog-artifactory.md)
- [Coder Module Registry](https://registry.coder.com/modules)

---

# Web IDEs in templates

Source: https://coder.com/docs/admin/templates/extending-templates/web-ides

In Coder, web IDEs are defined as
[coder_app](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
resources in the template. With our generic model, any web application can be
used as a Coder application. For example:

```tf
# Add button to open Portainer in the workspace dashboard
# Note: Portainer must be already running in the workspace
resource "coder_app" "portainer" {
  agent_id      = coder_agent.main.id
  slug          = "portainer"
  display_name  = "Portainer"
  icon          = "https://simpleicons.org/icons/portainer.svg"
  url           = "https://localhost:9443/api/status"

  healthcheck {
    url       = "https://localhost:9443/api/status"
    interval  = 6
    threshold = 10
  }
}
```

## code-server

[code-server](https://github.com/coder/code-server) is our supported method of running
VS Code in the web browser. A simple way to install code-server in Linux/macOS
workspaces is via the Coder agent in your template:

```console
# edit your template
cd your-template/
vim main.tf
```

```tf
resource "coder_agent" "main" {
    arch           = "amd64"
    os             = "linux"
    startup_script = <<EOF
    #!/bin/sh
    # install code-server
    # add '-s -- --version x.x.x' to install a specific code-server version
    curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server

    # start code-server on a specific port
    # authn is off since the user already authn-ed into the coder deployment
    # & is used to run the process in the background
    /tmp/code-server/bin/code-server --auth none --port 13337 &
    EOF
}
```

For advanced use, we recommend installing code-server in your VM snapshot or
container image. Here's a Dockerfile which leverages some special
[code-server features](https://coder.com/docs/code-server):

```dockerfile
FROM codercom/example-base:ubuntu

# install the latest version
USER root
RUN curl -fsSL https://code-server.dev/install.sh | sh
USER coder

# pre-install VS Code extensions
RUN code-server --install-extension eamodio.gitlens

# directly start code-server with the agent's startup_script (see above),
# or use a process manager like supervisord
```

You'll also need to specify a `coder_app` resource related to the agent. This is
how code-server is displayed on the workspace page.

```tf
resource "coder_app" "code-server" {
  agent_id     = coder_agent.main.id
  slug         = "code-server"
  display_name = "code-server"
  url          = "http://localhost:13337/?folder=/home/coder"
  icon         = "/icon/code.svg"
  subdomain    = false

  healthcheck {
    url       = "http://localhost:13337/healthz"
    interval  = 2
    threshold = 10
  }

}
```

![code-server in a workspace](../../../images/code-server-ide.png)

## VS Code Web

VS Code supports launching a local web client using the `code serve-web`
command. To add VS Code web as a web IDE, you have two options.

1. Install using the
   [vscode-web module](https://registry.coder.com/modules/vscode-web) from the
   coder registry.

   ```tf
   module "vscode-web" {
     source         = "registry.coder.com/modules/vscode-web/coder"
     version        = "1.0.14"
     agent_id       = coder_agent.main.id
     accept_license = true
   }
   ```

2. Install and start in your `startup_script` and create a corresponding
   `coder_app`

   ```tf
   resource "coder_agent" "main" {
       arch           = "amd64"
       os             = "linux"
       startup_script = <<EOF
       #!/bin/sh
       # install VS Code
       curl -Lk 'https://code.visualstudio.com/sha/download?build=stable&os=cli-alpine-x64' --output vscode_cli.tar.gz
       mkdir -p /tmp/vscode-cli
       tar -xf vscode_cli.tar.gz -C /tmp/vscode-cli
       rm vscode_cli.tar.gz
       # start the web server on a specific port
       /tmp/vscode-cli/code serve-web --port 13338 --without-connection-token  --accept-server-license-terms >/tmp/vscode-web.log 2>&1 &
       EOF
   }
   ```

   > `code serve-web` was introduced in version 1.82.0 (August 2023).

   You also need to add a `coder_app` resource for this.

   ```tf
   # VS Code Web
   resource "coder_app" "vscode-web" {
     agent_id     = coder_agent.coder.id
     slug         = "vscode-web"
     display_name = "VS Code Web"
     icon         = "/icon/code.svg"
     url          = "http://localhost:13338?folder=/home/coder"
     subdomain    = true  # Subdomain is recommended for best compatibility. Subpath mode now works via --server-base-path (added in VS Code 1.88, March 2024)
     share        = "owner"
   }
   ```

## Jupyter Notebook

To use Jupyter Notebook in your workspace, you can install it by using the
[Jupyter Notebook module](https://registry.coder.com/modules/jupyter-notebook)
from the Coder registry:

```tf
module "jupyter-notebook" {
  source   = "registry.coder.com/modules/jupyter-notebook/coder"
  version  = "1.0.19"
  agent_id = coder_agent.example.id
}
```

![Jupyter Notebook in Coder](../../../images/jupyter-notebook.png)

## JupyterLab

Configure your agent and `coder_app` like so to use Jupyter. Notice the
`subdomain=true` configuration:

```tf
data "coder_workspace" "me" {}

resource "coder_agent" "coder" {
  os             = "linux"
  arch           = "amd64"
  dir            = "/home/coder"
  startup_script = <<-EOF
pip3 install jupyterlab
$HOME/.local/bin/jupyter lab --ServerApp.token='' --ip='*'
EOF
}

resource "coder_app" "jupyter" {
  agent_id     = coder_agent.coder.id
  slug         = "jupyter"
  display_name = "JupyterLab"
  url          = "http://localhost:8888"
  icon         = "/icon/jupyter.svg"
  share        = "owner"
  subdomain    = true

  healthcheck {
    url       = "http://localhost:8888/healthz"
    interval  = 5
    threshold = 10
  }
}
```

Or Alternatively, you can use the JupyterLab module from the Coder registry:

```tf
module "jupyter" {
  source   = "registry.coder.com/modules/jupyter-lab/coder"
  version  = "1.0.0"
  agent_id = coder_agent.main.id
}
```

If you cannot enable a
[wildcard subdomain](../../../admin/setup/index.md#wildcard-access-url), you can
configure the template to run Jupyter on a path. There is however
[security risk](../../../reference/cli/server/index.md#--dangerous-allow-path-app-sharing)
running an app on a path and the template code is more complicated with coder
value substitution to recreate the path structure.

![JupyterLab in Coder](../../../images/jupyter.png)

## RStudio

Configure your agent and `coder_app` like so to use RStudio. Notice the
`subdomain=true` configuration:

```tf
resource "coder_agent" "coder" {
  os             = "linux"
  arch           = "amd64"
  dir            = "/home/coder"
  startup_script = <<EOT
#!/bin/bash
# start rstudio
/usr/lib/rstudio-server/bin/rserver --server-daemonize=1 --auth-none=1 &
EOT
}

resource "coder_app" "rstudio" {
  agent_id      = coder_agent.coder.id
  slug          = "rstudio"
  display_name  = "RStudio"
  icon          = "/icon/rstudio.svg"
  url           = "http://localhost:8787"
  subdomain     = true
  share         = "owner"

  healthcheck {
    url       = "http://localhost:8787/healthz"
    interval  = 3
    threshold = 10
  }
}
```

If you cannot enable a
[wildcard subdomain](https://coder.com/docs/admin/setup#wildcard-access-url),
you can configure the template to run RStudio on a path using an NGINX reverse
proxy in the template. There is however
[security risk](https://coder.com/docs/reference/cli/server#--dangerous-allow-path-app-sharing)
running an app on a path and the template code is more complicated with coder
value substitution to recreate the path structure.

[This](https://github.com/sempie/coder-templates/tree/main/rstudio) is a
community template example.

![RStudio in Coder](../../../images/rstudio-port-forward.png)

## Airflow

Configure your agent and `coder_app` like so to use Airflow. Notice the
`subdomain=true` configuration:

```tf
resource "coder_agent" "coder" {
  os   = "linux"
  arch = "amd64"
  dir  = "/home/coder"
  startup_script = <<EOT
#!/bin/bash
# install and start airflow
pip3 install apache-airflow
/home/coder/.local/bin/airflow standalone &
EOT
}

resource "coder_app" "airflow" {
  agent_id      = coder_agent.coder.id
  slug          = "airflow"
  display_name  = "Airflow"
  icon          = "/icon/airflow.svg"
  url           = "http://localhost:8080"
  subdomain     = true
  share         = "owner"

  healthcheck {
    url       = "http://localhost:8080/healthz"
    interval  = 10
    threshold = 60
  }
}
```

or use the [Airflow module](https://registry.coder.com/modules/apache-airflow)
from the Coder registry:

```tf
module "airflow" {
  source   = "registry.coder.com/modules/airflow/coder"
  version  = "1.0.13"
  agent_id = coder_agent.main.id
}
```

![Airflow in Coder](../../../images/airflow-port-forward.png)

## File Browser

To access the contents of a workspace directory in a browser, you can use File
Browser. File Browser is a lightweight file manager that allows you to view and
manipulate files in a web browser.

Show and manipulate the contents of the `/home/coder` directory in a browser.

```tf
resource "coder_agent" "coder" {
  os   = "linux"
  arch = "amd64"
  dir  = "/home/coder"
  startup_script = <<EOT
#!/bin/bash

curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
filebrowser --noauth --root /home/coder --port 13339 >/tmp/filebrowser.log 2>&1 &

EOT
}

resource "coder_app" "filebrowser" {
  agent_id     = coder_agent.coder.id
  display_name = "file browser"
  slug         = "filebrowser"
  url          = "http://localhost:13339"
  icon         = "https://raw.githubusercontent.com/matifali/logos/main/database.svg"
  subdomain    = true
  share        = "owner"

  healthcheck {
    url       = "http://localhost:13339/healthz"
    interval  = 3
    threshold = 10
  }
}
```

Or alternatively, you can use the
[`filebrowser`](https://registry.coder.com/modules/filebrowser) module from the
Coder registry:

```tf
module "filebrowser" {
  source   = "registry.coder.com/modules/filebrowser/coder"
  version  = "1.0.8"
  agent_id = coder_agent.main.id
}
```

![File Browser](../../../images/file-browser.png)

## SSH Fallback

If you prefer to run web IDEs in localhost, you can port forward using
[SSH](../../../user-guides/workspace-access/index.md#ssh) or the Coder CLI
`port-forward` sub-command. Some web IDEs may not support URL base path
adjustment so port forwarding is the only approach.

---

# Pre-install JetBrains IDEs in your template

Source: https://coder.com/docs/admin/templates/extending-templates/jetbrains-preinstall

For a faster first time connection with JetBrains IDEs, pre-install the IDEs backend in your template.

> [!NOTE]
> This guide only talks about installing the IDEs backend. For a complete guide on setting up JetBrains Gateway with client IDEs, refer to the [JetBrains Gateway air-gapped guide](./jetbrains-airgapped.md).

## Install the Client Downloader

Install the JetBrains Client Downloader binary:

```sh
wget -O jetbrains-clients-downloader-linux-x86_64.tar.gz \
  'https://data.services.jetbrains.com/products/download?code=JCD&platform=linux_x86-64' && \
tar -xzvf jetbrains-clients-downloader-linux-x86_64.tar.gz
rm jetbrains-clients-downloader-linux-x86_64.tar.gz
```

## Install Gateway backend

```sh
mkdir ~/JetBrains
./jetbrains-clients-downloader-linux-x86_64-*/bin/jetbrains-clients-downloader --products-filter <product-code> --build-filter <build-number> --platforms-filter linux-x64 --download-backends ~/JetBrains
```

For example, to install the build `243.26053.27` of IntelliJ IDEA:

```sh
./jetbrains-clients-downloader-linux-x86_64-*/bin/jetbrains-clients-downloader --products-filter IU --build-filter 243.26053.27 --platforms-filter linux-x64 --download-backends ~/JetBrains
tar -xzvf ~/JetBrains/backends/IU/*.tar.gz -C ~/JetBrains/backends/IU
rm -rf ~/JetBrains/backends/IU/*.tar.gz
```

## Register the Gateway backend

Add the following command to your template's `startup_script`:

```sh
~/JetBrains/*/bin/remote-dev-server.sh registerBackendLocationForGateway
```

## Configure JetBrains Gateway Module

If you are using our [jetbrains-gateway](https://registry.coder.com/modules/coder/jetbrains-gateway) module, you can configure it by adding the following snippet to your template:

```tf
module "jetbrains_gateway" {
  count          = data.coder_workspace.me.start_count
  source         = "registry.coder.com/modules/jetbrains-gateway/coder"
  version        = "1.0.29"
  agent_id       = coder_agent.main.id
  folder         = "/home/coder/example"
  jetbrains_ides = ["IU"]
  default        = "IU"
  latest         = false
  jetbrains_ide_versions = {
    "IU" = {
      build_number = "251.25410.129"
      version      = "2025.1"
    }
  }
}

resource "coder_agent" "main" {
    ...
    startup_script = <<-EOF
    ~/JetBrains/*/bin/remote-dev-server.sh registerBackendLocationForGateway
    EOF
}
```

## Dockerfile example

If you are using Docker based workspaces, you can add the command to your Dockerfile:

```dockerfile
FROM codercom/example-base:ubuntu

# JetBrains IDE installation (configurable)
ARG IDE_CODE=IU
ARG IDE_VERSION=2025.1

# Fetch and install IDE dynamically
RUN mkdir -p ~/JetBrains \
    && IDE_URL=$(curl -s "https://data.services.jetbrains.com/products/releases?code=${IDE_CODE}&majorVersion=${IDE_VERSION}&latest=true" | jq -r ".${IDE_CODE}[0].downloads.linux.link") \
    && IDE_NAME=$(curl -s "https://data.services.jetbrains.com/products/releases?code=${IDE_CODE}&majorVersion=${IDE_VERSION}&latest=true" | jq -r ".${IDE_CODE}[0].name") \
    && echo "Installing ${IDE_NAME}..." \
    && wget -q ${IDE_URL} -P /tmp \
    && tar -xzf /tmp/$(basename ${IDE_URL}) -C ~/JetBrains \
    && rm -f /tmp/$(basename ${IDE_URL}) \
    && echo "${IDE_NAME} installed successfully"
```

## Next steps

- [Pre-install the Client IDEs](./jetbrains-airgapped.md#1-deploy-the-server-and-install-the-client-downloader)

---

# JetBrains IDEs in an air-gapped environment

Source: https://coder.com/docs/admin/templates/extending-templates/jetbrains-airgapped

In networks that restrict access to the internet, you will need to leverage the
JetBrains Client Installer to download and save the IDE clients locally. Please
see the
[JetBrains documentation for more information](https://www.jetbrains.com/help/idea/fully-offline-mode.html).

This page is an example that the Coder team used as a proof-of-concept (POC) of the JetBrains Gateway Offline Mode solution.

We used Ubuntu on a virtual machine to test the steps.
If you have a suggestion or encounter an issue, please
[file a GitHub issue](https://github.com/coder/coder/issues/new?title=request%28docs%29%3A+jetbrains-airgapped+-+request+title+here%0D%0A&labels=["community","docs"]&body=doc%3A+%5Bjetbrains-airgapped%5D%28https%3A%2F%2Fcoder.com%2Fdocs%2Fuser-guides%2Fworkspace-access%2Fjetbrains%2Fjetbrains-airgapped%29%0D%0A%0D%0Aplease+enter+your+request+here%0D%0A).

## 1. Deploy the server and install the Client Downloader

Install the JetBrains Client Downloader binary. Note that the server must be a Linux-based distribution:

```sh
wget -O jetbrains-clients-downloader-linux-x86_64.tar.gz \
  'https://data.services.jetbrains.com/products/download?code=JCD&platform=linux_x86-64' && \
tar -xzvf jetbrains-clients-downloader-linux-x86_64.tar.gz
```

## 2. Install backends and clients

JetBrains Gateway requires both a backend to be installed on the remote host
(your Coder workspace) and a client to be installed on your local machine. You
can host both on the server in this example.

See here for the full
[JetBrains product list and builds](https://data.services.jetbrains.com/products).
Below is the full list of supported `--platforms-filter` values:

```console
windows-x64, windows-aarch64, linux-x64, linux-aarch64, osx-x64, osx-aarch64
```

To install both backends and clients, you will need to run two commands.

### Backends

```sh
mkdir ~/backends
./jetbrains-clients-downloader-linux-x86_64-*/bin/jetbrains-clients-downloader --products-filter <product-code> --build-filter <build-number> --platforms-filter linux-x64,windows-x64,osx-x64 --download-backends ~/backends
```

### Clients

This is the same command as above, with the `--download-backends` flag removed.

```sh
mkdir ~/clients
./jetbrains-clients-downloader-linux-x86_64-*/bin/jetbrains-clients-downloader --products-filter <product-code> --build-filter <build-number> --platforms-filter linux-x64,windows-x64,osx-x64 ~/clients
```

We now have both clients and backends installed.

## 3. Install a web server

You will need to run a web server in order to serve requests to the backend and
client files. We installed `nginx` and setup an FQDN and routed all requests to
`/`. See below:

```console
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                root /home/ubuntu;
        }
}
```

Then, configure your DNS entry to point to the IP address of the server. For the
purposes of the POC, we did not configure TLS, although that is a supported
option.

## 4. Add Client Files

You will need to add the following files on your local machine in order for
Gateway to pull the backend and client from the server.

```sh
$ cat productsInfoUrl # a path to products.json that was generated by the backend's downloader (it could be http://, https://, or file://)

https://internal.site/backends/<PRODUCT_CODE>/products.json

$ cat clientDownloadUrl # a path for clients that you got from the clients' downloader (it could be http://, https://, or file://)

https://internal.site/clients/

$ cat jreDownloadUrl # a path for JBR that you got from the clients' downloader (it could be http://, https://, or file://)

https://internal.site/jre/

$ cat pgpPublicKeyUrl # a URL to the KEYS file that was downloaded with the clients builds.

https://internal.site/KEYS
```

The location of these files will depend upon your local operating system:

<div class="tabs">

### macOS

```console
# User-specific settings
/Users/UserName/Library/Application Support/JetBrains/RemoteDev
# System-wide settings
/Library/Application Support/JetBrains/RemoteDev/
```

### Linux

```console
# User-specific settings
$HOME/.config/JetBrains/RemoteDev
# System-wide settings
/etc/xdg/JetBrains/RemoteDev/
```

### Windows

```console
# User-specific settings
HKEY_CURRENT_USER registry
# System-wide settings
HKEY_LOCAL_MACHINE registry
```

Additionally, create a string for each setting with its appropriate value in
`SOFTWARE\JetBrains\RemoteDev`:

![JetBrains offline - Windows](../../../images/gateway/jetbrains-offline-windows.png)

</div>

## 5. Setup SSH connection with JetBrains Gateway

With the server now configured, you can now configure your local machine to use
Gateway. Here is the documentation to
[setup SSH config via the Coder CLI](../../../user-guides/workspace-access/index.md#configure-ssh).
On the Gateway side, follow our guide here until step 16.

Instead of downloading from jetbrains.com, we will point Gateway to our server
endpoint. Select `Installation options...` and select `Use download link`. Note
that the URL must explicitly reference the archive file:

![Offline Gateway](../../../images/gateway/offline-gateway.png)

Select **Download IDE and Connect**.
Gateway should now download the backend and clients from the server into your remote workspace and local machine, respectively.

## Next steps

- [Pre-install the JetBrains IDEs backend in your workspace](./jetbrains-preinstall.md)

---

# Docker in Workspaces

Source: https://coder.com/docs/admin/templates/extending-templates/docker-in-workspaces

There are a few ways to run Docker within container-based Coder workspaces.

| Method                                                     | Description                                                                                                                                                        | Limitations                                                                                                                                                                                                                                        |
|------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Sysbox container runtime](#sysbox-container-runtime)      | Install the Sysbox runtime on your Kubernetes nodes or Docker host(s) for secure docker-in-docker and systemd-in-docker. Works with GKE, EKS, AKS, Docker.         | Requires [compatible nodes](https://github.com/nestybox/sysbox#host-requirements). [Limitations](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/limitations.md)                                                                    |
| [Envbox](#envbox)                                          | A container image with all the packages necessary to run an inner Sysbox container. Removes the need to setup sysbox-runc on your nodes. Works with GKE, EKS, AKS. | Requires running the outer container as privileged (the inner container that acts as the workspace is locked down). Requires compatible [nodes](https://github.com/nestybox/sysbox/blob/master/docs/distro-compat.md#sysbox-distro-compatibility). |
| [Rootless Podman](#rootless-podman)                        | Run Podman inside Coder workspaces. Does not require a custom runtime or privileged containers. Works with GKE, EKS, AKS, RKE, OpenShift                           | Requires smarter-device-manager for FUSE mounts. [See all](https://github.com/containers/podman/blob/main/rootless.md#shortcomings-of-rootless-podman)                                                                                             |
| [Privileged docker sidecar](#privileged-sidecar-container) | Run Docker as a privileged sidecar container.                                                                                                                      | Requires a privileged container. Workspaces can break out to root on the host machine.                                                                                                                                                             |

## Sysbox container runtime

The [Sysbox](https://github.com/nestybox/sysbox) container runtime allows
unprivileged users to run system-level applications, such as Docker, securely
from the workspace containers. Sysbox requires a
[compatible Linux distribution](https://github.com/nestybox/sysbox/blob/master/docs/distro-compat.md)
to implement these security features. Sysbox can also be used to run systemd
inside Coder workspaces. See [Systemd in Docker](#systemd-in-docker).

### Use Sysbox in Docker-based templates

After [installing Sysbox](https://github.com/nestybox/sysbox#installation) on
the Coder host, modify your template to use the sysbox-runc runtime:

```tf
resource "docker_container" "workspace" {
  # ...
  name    = "coder-${data.coder_workspace.me.owner}-${lower(data.coder_workspace.me.name)}"
  image   = "codercom/example-base:ubuntu"
  env     = ["CODER_AGENT_TOKEN=${coder_agent.main.token}"]
  command = ["sh", "-c", coder_agent.main.init_script]
  # Use the Sysbox container runtime (required)
  runtime = "sysbox-runc"
}

resource "coder_agent" "main" {
  arch           = data.coder_provisioner.me.arch
  os             = "linux"
  startup_script = <<-EOF
    #!/bin/sh
    set -e
    sudo service docker start
  EOF
}
```

### Use Sysbox in Kubernetes-based templates

After
[installing Sysbox on Kubernetes](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/install-k8s.md),
modify your template to use the sysbox-runc RuntimeClass. This requires the
Kubernetes Terraform provider version 2.16.0 or greater.

```tf
terraform {
  required_providers {
    coder = {
      source  = "coder/coder"
    }
    kubernetes = {
      source = "hashicorp/kubernetes"
      version = "2.16.0"
    }
  }
}

variable "workspaces_namespace" {
  default = "coder-namespace"
}

data "coder_workspace" "me" {}

resource "coder_agent" "main" {
  os   = "linux"
  arch = "amd64"
  dir  = "/home/coder"
  startup_script = <<-EOF
    #!/bin/sh
    set -e
    sudo service docker start
  EOF
}

resource "kubernetes_pod" "dev" {
  count = data.coder_workspace.me.start_count
  metadata {
    name      = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}"
    namespace = var.workspaces_namespace
    annotations = {
      "io.kubernetes.cri-o.userns-mode" = "auto:size=65536"
    }
  }

  spec {
  runtime_class_name = "sysbox-runc"
  # Use the Sysbox container runtime (required)
    security_context {
      run_as_user = 1000
      fs_group    = 1000
    }
    container {
      name = "dev"
      env {
        name  = "CODER_AGENT_TOKEN"
        value = coder_agent.main.token
      }
      image = "codercom/example-base:ubuntu"
      command = ["sh", "-c", coder_agent.main.init_script]
    }
  }
}
```

## Envbox

[Envbox](https://github.com/coder/envbox) is an image developed and maintained
by Coder that bundles the sysbox runtime. It works by starting an outer
container that manages the various sysbox daemons and spawns an unprivileged
inner container that acts as the user's workspace. The inner container is able
to run system-level software similar to a regular virtual machine (e.g.
`systemd`, `dockerd`, etc). Envbox offers the following benefits over running
sysbox directly on the nodes:

- No custom runtime installation or management on your Kubernetes nodes.
- No limit to the number of pods that run envbox.

Some drawbacks include:

- The outer container must be run as privileged
  - Note: the inner container is _not_ privileged. For more information on the
    security of sysbox containers see sysbox's
    [official documentation](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/security.md).
- Initial workspace startup is slower than running `sysbox-runc` directly on the
  nodes. This is due to `envbox` having to pull the image to its own Docker
  cache on its initial startup. Once the image is cached in `envbox`, startup
  performance is similar.

Envbox requires the same kernel requirements as running sysbox directly on the
nodes. Refer to sysbox's
[compatibility matrix](https://github.com/nestybox/sysbox/blob/master/docs/distro-compat.md#sysbox-distro-compatibility)
to ensure your nodes are compliant.

To get started with `envbox` check out the
[starter template](../../../../examples/templates/kubernetes-envbox)
or visit the [repo](https://github.com/coder/envbox).

<a id="authenticating-with-a-private-registry"></a>

### Authenticate with a private registry

Authenticating with a private container registry can be done by referencing the
credentials via the `CODER_IMAGE_PULL_SECRET` environment variable. It is
encouraged to populate this
[environment variable](https://kubernetes.io/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data)
by using a Kubernetes
[secret](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#registry-secret-existing-credentials).

Refer to your container registry documentation to understand how to best create
this secret.

The following shows a minimal example using a the JSON API key from a GCP
service account to pull a private image:

```sh
# Create the secret
$ kubectl create secret docker-registry <name> \
  --docker-server=us.gcr.io \
  --docker-username=_json_key \
  --docker-password="$(cat ./json-key-file.yaml)" \
  --docker-email=<service-account-email>
```

```tf
env {
  name = "CODER_IMAGE_PULL_SECRET"
  value_from {
    secret_key_ref {
      name = "<name>"
      key = ".dockerconfigjson"
    }
  }
}
```

## Rootless podman

[Podman](https://docs.podman.io/en/latest/) is Docker alternative that is
compatible with OCI containers specification. which can run rootless inside
Kubernetes pods. No custom RuntimeClass is required.

Before using Podman, please review the following documentation:

- [Basic setup and use of Podman in a rootless environment](https://github.com/containers/podman/blob/main/docs/tutorials/rootless_tutorial.md)

- [Shortcomings of Rootless Podman](https://github.com/containers/podman/blob/main/rootless.md#shortcomings-of-rootless-podman)

1. Enable
   [smart-device-manager](https://github.com/smarter-project/smarter-device-manager#enabling-access)
   to securely expose a FUSE devices to pods.

   ```sh
   cat <<EOF | kubectl create -f -
   apiVersion: apps/v1
   kind: DaemonSet
   metadata:
     name: fuse-device-plugin-daemonset
     namespace: kube-system
   spec:
     selector:
       matchLabels:
         name: fuse-device-plugin-ds
     template:
       metadata:
         labels:
           name: fuse-device-plugin-ds
       spec:
         hostNetwork: true
         containers:
         - name: fuse-device-plugin-ctr
           image: soolaugust/fuse-device-plugin:v1.0
           securityContext:
             allowPrivilegeEscalation: false
             capabilities:
               drop: ["ALL"]
           volumeMounts:
           - name: device-plugin
             mountPath: /var/lib/kubelet/device-plugins
         volumes:
         - name: device-plugin
           hostPath:
             path: /var/lib/kubelet/device-plugins
         imagePullSecrets:
         - name: registry-secret
   EOF
   ```

2. Be sure to label your nodes to enable smarter-device-manager:

   ```sh
   kubectl get nodes
   kubectl label nodes --all smarter-device-manager=enabled
   ```

   > ⚠️ **Warning**: If you are using a managed Kubernetes distribution (e.g.
   > AKS, EKS, GKE), be sure to set node labels via your cloud provider.
   > Otherwise, your nodes may drop the labels and break podman functionality.

3. For systems running SELinux (typically Fedora-, CentOS-, and Red Hat-based
   systems), you might need to disable SELinux or set it to permissive mode.

4. Create a template from the built-in `kubernetes` starter, then adapt it for rootless Podman:

   ```sh
   coder templates init --id kubernetes ./kubernetes-podman
   cd ./kubernetes-podman
   ```

   The `kubernetes` starter already runs the workspace pod as a non-root user (`run_as_user = 1000`, `fs_group = 1000`, `run_as_non_root = true`), which rootless Podman requires. In the generated `main.tf`, apply the Podman changes to the `kubernetes_deployment_v1.main` pod template (marked `# Podman` in the following snippet):

   ```tf
   spec {
     template {
       metadata {
         # ...
         # Podman: allow Podman to create nested containers. The annotation
         # key must match the container name below (`dev`).
         annotations = {
           "container.apparmor.security.beta.kubernetes.io/dev" = "unconfined"
         }
       }
       spec {
         # The starter already sets these; rootless Podman requires them.
         security_context {
           run_as_user     = 1000
           fs_group        = 1000
           run_as_non_root = true
         }

         container {
           name = "dev"
           # Podman: base image with Podman and fuse-overlayfs preinstalled.
           image = "codercom/example-podman:ubuntu"
           # ...
           resources {
             limits = {
               # ...
               # Podman: FUSE device exposed by smarter-device-manager (step 1).
               "github.com/fuse" = "1"
             }
           }
         }
       }
     }
   }
   ```

   The `codercom/example-podman` image is built and maintained in
   [`coder/images`](https://github.com/coder/images).

   > On Kubernetes 1.30+, the
   > `container.apparmor.security.beta.kubernetes.io/<container>` annotation is
   > deprecated in favor of the `securityContext.appArmorProfile` field. The
   > annotation still works and remains the most broadly compatible option, so
   > switch to the field once your cluster and Terraform Kubernetes provider
   > both support it.

   Push the template to your deployment:

   ```sh
   coder templates push
   ```

   > For more information around the requirements of rootless podman pods, see:
   > [How to run Podman inside of Kubernetes](https://www.redhat.com/sysadmin/podman-inside-kubernetes)

### Rootless Podman on Bottlerocket nodes

Rootless containers rely on Linux user-namespaces.
[Bottlerocket](https://github.com/bottlerocket-os/bottlerocket) disables them by default (`user.max_user_namespaces = 0`), so Podman commands will return an error until you raise the limit:

```txt
cannot clone: Invalid argument
user namespaces are not enabled in /proc/sys/user/max_user_namespaces
```

1. Add a `user.max_user_namespaces` value to your Bottlerocket user data to use rootless Podman on the node:

  ```toml
  [settings.kernel.sysctl]
  "user.max_user_namespaces" = "65536"
  ```

1. Reboot the node.
1. Verify that the value is more than `0`:

  ```sh
  sysctl -n user.max_user_namespaces
  ```

For Karpenter-managed Bottlerocket nodes, add the `user.max_user_namespaces` setting in your `EC2NodeClass`:

```yaml
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: bottlerocket-rootless
spec:
  amiFamily: Bottlerocket # required for BR-style userData
  # …
  userData: |
    [settings.kernel]
    sysctl = { "user.max_user_namespaces" = "65536" }
```

### Rootless Podman on EKS Auto Mode

The `EC2NodeClass` above applies to self-managed Karpenter nodes. On EKS Auto Mode, the built-in `NodeClass` (`eks.amazonaws.com`) doesn't expose `userData` or kernel sysctls, so `user.max_user_namespaces` stays at `0` with no way to raise it on those nodes. Run Podman workspaces on a separate managed node group instead; the default AL2023 AMIs ship with user namespaces enabled.

> On a brand-new Auto Mode cluster, install the `vpc-cni` and `kube-proxy` add-ons before your managed node group can reach `Ready`.

## Privileged sidecar container

A
[privileged container](https://docs.docker.com/engine/containers/run/#runtime-privilege-and-linux-capabilities)
can be added to your templates to add docker support. This may come in handy if
your nodes cannot run Sysbox.

> [!WARNING]
> This is insecure. Workspaces will be able to gain root access to the host machine.

### Use a privileged sidecar container in Docker-based templates

```tf
resource "coder_agent" "main" {
  os             = "linux"
  arch           = "amd64"
}

resource "docker_network" "private_network" {
  name = "network-${data.coder_workspace.me.id}"
}

resource "docker_container" "dind" {
  image      = "docker:dind"
  privileged = true
  name       = "dind-${data.coder_workspace.me.id}"
  entrypoint = ["dockerd", "-H", "tcp://0.0.0.0:2375"]
  networks_advanced {
    name = docker_network.private_network.name
  }
}

resource "docker_container" "workspace" {
  count   = data.coder_workspace.me.start_count
  image   = "codercom/example-base:ubuntu"
  name    = "dev-${data.coder_workspace.me.id}"
  command = ["sh", "-c", coder_agent.main.init_script]
  env = [
    "CODER_AGENT_TOKEN=${coder_agent.main.token}",
    "DOCKER_HOST=${docker_container.dind.name}:2375"
  ]
  networks_advanced {
    name = docker_network.private_network.name
  }
}
```

### Use a privileged sidecar container in Kubernetes-based templates

```tf
terraform {
  required_providers {
    coder = {
      source  = "coder/coder"
    }
    kubernetes = {
      source = "hashicorp/kubernetes"
      version = "2.16.0"
    }
  }
}

variable "workspaces_namespace" {
  default = "coder-namespace"
}

data "coder_workspace" "me" {}

resource "coder_agent" "main" {
  os             = "linux"
  arch           = "amd64"
}

resource "kubernetes_pod" "main" {
  count = data.coder_workspace.me.start_count
  metadata {
    name      = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}"
    namespace = var.namespace
  }
  spec {
    # Run a privileged dind (Docker in Docker) container
    container {
      name  = "docker-sidecar"
      image = "docker:dind"
      security_context {
        privileged = true
        run_as_user = 0
      }
      command = ["dockerd", "-H", "tcp://127.0.0.1:2375"]
    }
    container {
      name    = "dev"
      image   = "codercom/example-base:ubuntu"
      command = ["sh", "-c", coder_agent.main.init_script]
      security_context {
        run_as_user = "1000"
      }
      env {
        name  = "CODER_AGENT_TOKEN"
        value = coder_agent.main.token
      }
      # Use the Docker daemon in the "docker-sidecar" container
      env {
        name  = "DOCKER_HOST"
        value = "localhost:2375"
      }
    }
  }
}
```

## Systemd in Docker

Additionally, [Sysbox](https://github.com/nestybox/sysbox) can be used to give
workspaces full `systemd` capabilities.

After
[installing Sysbox on Kubernetes](https://github.com/nestybox/sysbox/blob/master/docs/user-guide/install-k8s.md),
modify your template to use the sysbox-runc RuntimeClass. This requires the
Kubernetes Terraform provider version 2.16.0 or greater.

```tf
terraform {
  required_providers {
    coder = {
      source  = "coder/coder"
    }
    kubernetes = {
      source = "hashicorp/kubernetes"
      version = "2.16.0"
    }
  }
}

variable "workspaces_namespace" {
  default = "coder-namespace"
}

data "coder_workspace" "me" {}

resource "coder_agent" "main" {
  os   = "linux"
  arch = "amd64"
  dir  = "/home/coder"
}

resource "kubernetes_pod" "dev" {
  count = data.coder_workspace.me.start_count
  metadata {
    name      = "coder-${data.coder_workspace.me.owner}-${data.coder_workspace.me.name}"
    namespace = var.workspaces_namespace
    annotations = {
      "io.kubernetes.cri-o.userns-mode" = "auto:size=65536"
    }
  }

  spec {

    # Use Sysbox container runtime (required)
    runtime_class_name = "sysbox-runc"

    # Run as root in order to start systemd (required)
    security_context {
      run_as_user = 0
      fs_group    = 0
    }

    container {
      name = "dev"
      env {
        name  = "CODER_AGENT_TOKEN"
        value = coder_agent.main.token
      }
      image = "codercom/example-base:ubuntu"
      command = ["sh", "-c", <<EOF
    # Start the Coder agent as the "coder" user
    # once systemd has started up
    sudo -u coder --preserve-env=CODER_AGENT_TOKEN /bin/bash -- <<-'    EOT' &
    while [[ ! $(systemctl is-system-running) =~ ^(running|degraded) ]]
    do
      echo "Waiting for system to start... $(systemctl is-system-running)"
      sleep 2
    done
    ${coder_agent.main.init_script}
    EOT

    exec /sbin/init
    EOF
      ]
    }
  }
}
```

---

# Workspace Tags

Source: https://coder.com/docs/admin/templates/extending-templates/workspace-tags

Template administrators can leverage static template tags to limit workspace
provisioning to designated provisioner groups that have locally deployed
credentials for creating workspace resources. While this method ensures
controlled access, it offers limited flexibility and does not permit users to
select the nodes for their workspace creation.

By using `coder_workspace_tags` and `coder_parameter`s, template administrators
can enable dynamic tag selection and modify static template tags.

## Dynamic tag selection

Here is a sample `coder_workspace_tags` data resource with a few workspace tags
specified:

```tf
data "coder_workspace_tags" "custom_workspace_tags" {
  tags = {
    "az"          = var.az
    "zone"        = "developers"
    "runtime"     = data.coder_parameter.runtime_selector.value
    "project_id"  = "PROJECT_${data.coder_parameter.project_name.value}"
    "cache"       = data.coder_parameter.feature_cache_enabled.value == "true" ? "with-cache" : "no-cache"
  }
}
```

### Legend

- `zone` - static tag value set to `developers`
- `runtime` - supported by the string-type `coder_parameter` to select
  provisioner runtime, `runtime_selector`
- `project_id` - a formatted string supported by the string-type
  `coder_parameter`, `project_name`
- `cache` - an HCL condition involving boolean-type `coder_parameter`,
  `feature_cache_enabled`

Review the
[full template example](../../../../examples/workspace-tags)
using `coder_workspace_tags` and `coder_parameter`s.

## How it Works

In order to correctly import a template that defines tags in
`coder_workspace_tags`, Coder needs to know the tags to assign the template
import job ahead of time. To work around this chicken-and-egg problem, Coder
performs static analysis of the Terraform to determine a reasonable set of tags
to assign to the template import job. This happens _before_ the job is started.

When the template is imported, Coder will then store the _raw_ Terraform
expressions for the values of the workspace tags for that template version. The
next time a workspace is created from that template, Coder retrieves the stored
raw values from the database and evaluates them using provided template
variables and parameters. This is illustrated in the table below:

| Value Type | Template Import                                    | Workspace Creation      |
|------------|----------------------------------------------------|-------------------------|
| Static     | `{"region": "us"}`                                 | `{"region": "us"}`      |
| Variable   | `{"az": var.az}`                                   | `{"region": "us-east"}` |
| Parameter  | `{"cluster": data.coder_parameter.cluster.value }` | `{"cluster": "dev"}`    |

## Constraints

### Tagged provisioners

It is possible to choose tag combinations that no provisioner can handle. This
will cause the provisioner job to get stuck in the queue until a provisioner is
added that can handle its combination of tags.

Before releasing the template version with configurable workspace tags, ensure
that every tag set is associated with at least one healthy provisioner.

> [!NOTE]
> It may be useful to run at least one provisioner with no additional
> tag restrictions that is able to take on any job.
>
> `coder_workspace_tags` are cumulative.
> Jobs will only match provisioners that have all tags defined in both your template configuration and `coder_workspace_tags`.

### Parameters types

Provisioners require job tags to be defined in plain string format. When a
workspace tag refers to a `coder_parameter` without involving the string
formatter, for example,
(`"runtime" = data.coder_parameter.runtime_selector.value`), the Coder
provisioner server can transform only the following parameter types to strings:
_string_, _number_, and _bool_.

### Mutability

A mutable `coder_parameter` can be dangerous for a workspace tag as it allows
the workspace owner to change a provisioner group (due to different tags). In
most cases, `coder_parameter`s backing `coder_workspace_tags` should be marked
as immutable and set only once, during workspace creation.

You may only specify the following as inputs for `coder_workspace_tags`:

|                    | Example                                       |
|:-------------------|:----------------------------------------------|
| Static values      | `"developers"`                                |
| Template variables | `var.az`                                      |
| Coder parameters   | `data.coder_parameter.runtime_selector.value` |

Passing template tags in from other data sources or resources is not permitted.

### HCL syntax

When importing the template version with `coder_workspace_tags`, the Coder provisioner server extracts raw partial queries for each workspace tag and stores them in the database.
During workspace build time, the control plane uses the [HashiCorp HCL library](https://github.com/hashicorp/hcl) to evaluate these raw queries on-the-fly without processing the entire Terraform template.
This evaluation is simpler but also limited in terms of available functions, variables, and references to other resources.

#### Supported syntax

- Static string: `foobar_tag = "foobaz"`
- Formatted string: `foobar_tag = "foobaz ${data.coder_parameter.foobaz.value}"`
- Reference to `coder_parameter`:
  `foobar_tag = data.coder_parameter.foobar.value`
- Boolean logic: `production_tag = !data.coder_parameter.staging_env.value`
- Condition:
  `cache = data.coder_parameter.feature_cache_enabled.value == "true" ? "with-cache" : "no-cache"`

#### Not supported

- Function calls that reference files on disk: `abspath`, `file*`, `pathexpand`
- Resources: `compute_instance.dev.name`
- Data sources other than `coder_parameter`: `data.local_file.hostname.content`

---

# Provider Authentication

Source: https://coder.com/docs/admin/templates/extending-templates/provider-authentication

> [!CAUTION]
> Do not store secrets in templates. Assume every user has cleartext access to every template.

The control plane's
[provisioner](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/provisioner)
process needs to authenticate with other provider APIs to provision workspaces.
There are two approaches to do this:

- Pass credentials to the provisioner as parameters.
- Preferred: Run the control plane in an environment that is authenticated
  with the provider.

We encourage the latter approach where supported:

- Simplifies the template.
- Keeps provider credentials out of Coder's database, making it a less valuable
  target for attackers.
- Compatible with agent-based authentication schemes, which handle credential
  rotation or ensure the credentials are not written to disk.

Generally, you can set up an environment to provide credentials to Coder in
these ways:

- A well-known location on disk. For example, `~/.aws/credentials` for AWS on
  POSIX systems.
- Environment variables.

It is usually sufficient to authenticate using the CLI or SDK for the provider
before running Coder, but check the Terraform provider's documentation for
details.

These platforms have Terraform providers that support authenticated
environments:

- [Google Cloud](https://registry.terraform.io/providers/hashicorp/google/latest/docs)
- [Amazon Web Services](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)
- [Microsoft Azure](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs)
- [Kubernetes](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs)
- [Docker](https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs)

## Use a remote Docker host for authentication

There are two ways to use a remote Docker host for authentication:

- Configure the Docker provider to use a
  [remote host over SSH or TCP](https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs#remote-hosts).
- Run an [external provisioner](../../../install/operate/provisioners/index.md) on the remote docker
  host.

Other providers might also support authenticated environments. Check the
[documentation of the Terraform provider](https://registry.terraform.io/browse/providers)
for details.

---

# Dev Containers

Source: https://coder.com/docs/admin/templates/extending-templates/devcontainers

Dev containers extend your template with containerized development environments,
allowing developers to work in consistent, reproducible setups defined by
`devcontainer.json` files.

Coder's Dev Containers Integration uses the standard `@devcontainers/cli` and
Docker to run containers inside workspaces.

For setup instructions, see
[Dev Containers Integration](../../integrations/devcontainers/integration.md).

For an alternative approach that doesn't require Docker, see
[Envbuilder](../../integrations/devcontainers/envbuilder/index.md).

---

# Improve agent resiliency

Source: https://coder.com/docs/admin/templates/extending-templates/process-priority

Coder's agent can automatically lower the scheduling priority
and raise the OOM (out-of-memory) kill score of user processes
so the agent itself stays alive under resource pressure.

## Prerequisites

- **Linux** — The feature is ignored on other operating systems.
- **`CAP_SYS_NICE`** — Required if the agent needs to lower
  the nice value below its current value. In Kubernetes, add
  it to the container's security context:

  ```tf
  container {
    security_context {
      capabilities {
        add = ["CAP_SYS_NICE"]
      }
    }
  }
  ```

## Environment variables

Configure the feature with environment variables in the
environment that launches the agent binary. These must be set
on the workspace container or host, not in the `coder_agent`
resource's `env` block — the agent reads them from its own
process environment at startup.

| Variable                | Required | Default                       | Description                                                                                                                                                                                   |
|-------------------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `CODER_PROC_PRIO_MGMT`  | Yes      | —                             | Set to enable the feature. The agent checks whether the variable is present, not its value — even an empty string enables it. Use `1` by convention. To disable, unset the variable entirely. |
| `CODER_PROC_OOM_SCORE`  | No       | Computed from agent's score   | Explicit `oom_score_adj` value for child processes. Range: `-1000` to `1000`.                                                                                                                 |
| `CODER_PROC_NICE_SCORE` | No       | Agent nice + 5 (capped at 19) | Explicit nice value for child processes. Range: `-20` to `19` (higher = lower priority).                                                                                                      |

### OOM score defaults

If you do not set `CODER_PROC_OOM_SCORE`, the agent computes a
value based on its own `oom_score_adj`:

| Agent's `oom_score_adj` | Child score | Rationale                                      |
|-------------------------|-------------|------------------------------------------------|
| Negative (< 0)          | `0`         | Children are treated as normal processes.      |
| >= 998                  | `1000`      | Children get the maximum score (killed first). |
| Any other value         | `998`       | Children get a near-maximum score.             |

The goal is for the kernel's OOM killer to target child
processes before the agent, keeping remote connectivity alive
even when a workspace runs out of memory.

### Nice score defaults

If you do not set `CODER_PROC_NICE_SCORE`, the agent sets
children to its own nice value plus 5, capped at 19. This
gives the agent more CPU scheduling priority than user
workloads.

## Example

The following Kubernetes template snippet enables process
priority management on the workspace container:

```tf
resource "kubernetes_deployment" "workspace" {
  # ... other configuration

  spec {
    template {
      spec {
        container {
          name  = "dev"
          image = "codercom/example-base:ubuntu"

          env {
            name  = "CODER_AGENT_TOKEN"
            value = coder_agent.main.token
          }
          env {
            name  = "CODER_PROC_PRIO_MGMT"
            value = "1"
          }
          env {
            name  = "CODER_PROC_OOM_SCORE"
            value = "10"
          }
          env {
            name  = "CODER_PROC_NICE_SCORE"
            value = "1"
          }

          security_context {
            capabilities {
              add = ["CAP_SYS_NICE"]
            }
          }
        }
      }
    }
  }
}
```

- `CODER_PROC_OOM_SCORE=10` gives child processes a slightly
  elevated OOM score while keeping them well below the maximum.
- `CODER_PROC_NICE_SCORE=1` gives children a mildly lower CPU
  priority than the agent.
- `CAP_SYS_NICE` allows the agent to set nice values.

## Troubleshooting

### OOM score adjustment fails

If you see `failed to adjust oom score` in stderr but the
process still starts, the agent likely lacks permission to
write to `/proc/self/oom_score_adj`. Ensure the process is
dumpable — this is handled automatically by the agent, but
can fail if the container runtime restricts `prctl` calls.

### Nice value is not applied

If you see `failed to adjust niceness` in stderr, nice values
can only be increased (lowered in priority) without
`CAP_SYS_NICE`. If your template sets a `CODER_PROC_NICE_SCORE`
lower than the agent's current nice value, add the capability
to the container's security context.

### Environment variables leak to nested Coder agents

The agent strips all `CODER_PROC_*` variables from child
environments automatically. This prevents interference in
"Coder on Coder" development scenarios where a workspace
runs another Coder agent.

<a id="verifying-the-feature-is-enabled"></a>

### Verify the feature is enabled

The agent logs whether process priority management is active
at startup. Look for these lines in the agent log:

```txt
"process priority management enabled"
"process priority management not enabled (linux-only)"
```

The log entry includes the `CODER_PROC_PRIO_MGMT` value and
the operating system. Check the agent log file at
`<log-dir>/coder-agent.log` or stderr output.

### Feature has no effect on macOS or Windows

Process priority management is Linux-only. Setting
`CODER_PROC_PRIO_MGMT` on other operating systems is safe
but has no effect.

---

# Workspace process logging

Source: https://coder.com/docs/admin/templates/extending-templates/process-logging

The workspace process logging feature allows you to log all system-level
processes executing in the workspace.

This feature is only available on Linux in Kubernetes. There are
additional requirements outlined further in this document.

> [!NOTE]
> Workspace process logging is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Workspace process logging adds a sidecar container to workspace pods that will
log all processes started in the workspace container (e.g., commands executed in
the terminal or processes created in the background by other processes).
Processes launched inside containers or nested containers within the workspace
are also logged. You can view the output from the sidecar or send it to a
monitoring stack, such as CloudWatch, for further analysis or long-term storage.

Please note that these logs are not recorded or captured by the Coder
organization in any way, shape, or form.

## How this works

Coder uses [eBPF](https://ebpf.io/) (which we chose for its minimal performance
impact) to perform in-kernel logging and filtering of all exec system calls
originating from the workspace container.

The core of this feature is also open source and can be found in the
[exectrace](https://github.com/coder/exectrace) GitHub repo. The enterprise
component (in the `enterprise/` directory of the repo) is responsible for
starting the eBPF program with the correct filtering options for the specific
workspace.

## Requirements

The host machine must be running a Linux kernel >= 5.8 with the kernel config
`CONFIG_DEBUG_INFO_BTF=y` enabled.

To check your kernel version, run:

```sh
uname -r
```

To validate the required kernel config is enabled, run either of the following
commands on your nodes directly (_not_ from a workspace terminal):

```sh
cat /proc/config.gz | gunzip | grep CONFIG_DEBUG_INFO_BTF
```

```sh
cat "/boot/config-$(uname -r)" | grep CONFIG_DEBUG_INFO_BTF
```

If these requirements are not met, workspaces will fail to start for security
reasons.

Your template must be a Kubernetes template. Workspace process logging is not
compatible with the `sysbox-runc` runtime due to technical limitations, but it
is compatible with our `envbox` template family.

## Example templates

We provide working example templates for Kubernetes, and Kubernetes with
`envbox` (for [Docker support in workspaces](./docker-in-workspaces.md)). You
can view these templates in the
[exectrace repo](https://github.com/coder/exectrace/tree/main/enterprise/templates).

<a id="configuring-custom-templates-to-use-workspace-process-logging"></a>

## Configure custom templates to use workspace process logging

If you have an existing Kubernetes or Kubernetes with `envbox` template that you
would like to add workspace process logging to, follow these steps:

1. Ensure the image used in your template has `curl` installed.

1. Add the following section to your template's `main.tf` file:

   <!--
     If you are updating this section, please also update the example templates
     in the exectrace repo.
   -->

   ```tf
   locals {
     # This is the init script for the main workspace container that runs before the
     # agent starts to configure workspace process logging.
     exectrace_init_script = <<EOT
       set -eu
       pidns_inum=$(readlink /proc/self/ns/pid | sed 's/[^0-9]//g')
       if [ -z "$pidns_inum" ]; then
         echo "Could not determine process ID namespace inum"
         exit 1
       fi

       # Before we start the script, does curl exist?
       if ! command -v curl >/dev/null 2>&1; then
         echo "curl is required to download the Coder binary"
         echo "Please install curl to your image and try again"
         # 127 is command not found.
         exit 127
       fi

       echo "Sending process ID namespace inum to exectrace sidecar"
       rc=0
       max_retry=5
       counter=0
       until [ $counter -ge $max_retry ]; do
         set +e
         curl \
           --fail \
           --silent \
           --connect-timeout 5 \
           -X POST \
           -H "Content-Type: text/plain" \
           --data "$pidns_inum" \
           http://127.0.0.1:56123
         rc=$?
         set -e
         if [ $rc -eq 0 ]; then
           break
         fi

         counter=$((counter+1))
         echo "Curl failed with exit code $${rc}, attempt $${counter}/$${max_retry}; Retrying in 3 seconds..."
         sleep 3
       done
       if [ $rc -ne 0 ]; then
         echo "Failed to send process ID namespace inum to exectrace sidecar"
         exit $rc
       fi

     EOT
   }
   ```

1. Update the `command` of your workspace container like the following:

   <!--
     If you are updating this section, please also update the example templates
     in the exectrace repo.
   -->

   ```tf
   resource "kubernetes_pod" "main" {
     ...
     spec {
       ...
       container {
         ...
         // NOTE: this command is changed compared to the upstream kubernetes
         // template
         command = [
           "sh",
           "-c",
           "${local.exectrace_init_script}\n\n${coder_agent.main.init_script}",
         ]
         ...
       }
       ...
     }
     ...
   }
   ```

   > [!NOTE]
   > If you are using the `envbox` template, you will need to update
   > the third argument to be
   > `"${local.exectrace_init_script}\n\nexec /envbox docker"` instead.

1. Add the following container to your workspace pod spec.

   <!--
     If you are updating this section, please also update the example templates
     in the exectrace repo.
   -->

   ```tf
   resource "kubernetes_pod" "main" {
     ...
     spec {
       ...
       // NOTE: this container is added compared to the upstream kubernetes
       // template
       container {
         name              = "exectrace"
         image             = "ghcr.io/coder/exectrace:latest"
         image_pull_policy = "Always"
         command = [
           "/opt/exectrace",
           "--init-address", "127.0.0.1:56123",
           "--label", "workspace_id=${data.coder_workspace.me.id}",
           "--label", "workspace_name=${data.coder_workspace.me.name}",
           "--label", "user_id=${data.coder_workspace_owner.me.id}",
           "--label", "username=${data.coder_workspace_owner.me.name}",
           "--label", "user_email=${data.coder_workspace_owner.me.email}",
         ]
         security_context {
           // exectrace must be started as root so it can attach probes into the
           // kernel to record process events with high throughput.
           run_as_user  = "0"
           run_as_group = "0"
           // exectrace requires a privileged container so it can control mounts
           // and perform privileged syscalls against the host kernel to attach
           // probes.
           privileged = true
         }
       }
       ...
     }
     ...
   }
   ```

   > [!NOTE]
   > `exectrace` requires root privileges and a privileged container
   > to attach probes to the kernel. This is a requirement of eBPF.

1. Add the following environment variable to your workspace pod:

   <!--
     If you are updating this section, please also update the example templates
     in the exectrace repo.
   -->

   ```tf
   resource "kubernetes_pod" "main" {
     ...
     spec {
       ...
       env {
         name = "CODER_AGENT_SUBSYSTEM"
         value = "exectrace"
       }
       ...
     }
     ...
   }
   ```

Once you have made these changes, you can push a new version of your template
and workspace process logging will be enabled for all workspaces once they are
restarted.

<a id="viewing-workspace-process-logs"></a>

## View workspace process logs

To view the process logs for a specific workspace you can use `kubectl` to print
the logs:

```sh
kubectl logs pod-name --container exectrace
```

The raw logs will look something like this:

```json
{
    "ts": "2022-02-28T20:29:38.038452202Z",
    "level": "INFO",
    "msg": "exec",
    "fields": {
        "labels": {
            "user_email": "jessie@coder.com",
            "user_id": "5e876e9a-121663f01ebd1522060d5270",
            "username": "jessie",
            "workspace_id": "621d2e52-a6987ef6c56210058ee2593c",
            "workspace_name": "main"
        },
        "cmdline": "uname -a",
        "event": {
            "filename": "/usr/bin/uname",
            "argv": ["uname", "-a"],
            "truncated": false,
            "pid": 920684,
            "uid": 101000,
            "gid": 101000,
            "comm": "bash"
        }
    }
}
```

### View logs in AWS EKS

If you're using AWS' Elastic Kubernetes Service, you can
[configure your cluster](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Container-Insights-EKS-logs.html)
to send logs to CloudWatch. This allows you to view the logs for a specific user
or workspace.

To view your logs, go to the CloudWatch dashboard (which is available on the
**Log Insights** tab) and run a query similar to the following:

```txt
fields @timestamp, log_processed.fields.cmdline
| sort @timestamp asc
| filter kubernetes.container_name="exectrace"
| filter log_processed.fields.labels.username="zac"
| filter log_processed.fields.labels.workspace_name="code"
```

## Usage considerations

- The sidecar attached to each workspace is a privileged container, so you may
  need to review your organization's security policies before enabling this
  feature. Enabling workspace process logging does _not_ grant extra privileges
  to the workspace container itself, however.
- `exectrace` will log processes from nested Docker containers (including deeply
  nested containers) correctly, but Coder does not distinguish between processes
  started in the workspace and processes started in a child container in the
  logs.
- With `envbox` workspaces, this feature will detect and log startup processes
  begun in the outer container (including container initialization processes).
- Because this feature logs **all** processes in the workspace, high levels of
  usage (e.g., during a `make` run) will result in an abundance of output in the
  sidecar container. Depending on how your Kubernetes cluster is configured, you
  may incur extra charges from your cloud provider to store the additional logs.

---

# Workspace startup coordination

Source: https://coder.com/docs/admin/templates/startup-coordination

> [!NOTE]
> This feature is experimental and may change without notice in future releases.

When workspaces start, scripts often need to run in a specific order.
For example, an IDE or coding agent might need the repository cloned
before it can start. Without explicit coordination, these scripts can
race against each other, leading to startup failures and inconsistent
workspace states.

Coder's workspace startup coordination feature lets you declare
dependencies between startup scripts and ensure they run in the correct order.
This eliminates race conditions and makes workspace startup predictable and
reliable.

## Why use this?

Simply placing all of your workspace initialization logic in a single script works, but leads to slow workspace startup times.
Breaking this out into multiple independent `coder_script` resources improves startup times by allowing the scripts to run in parallel.
However, this can lead to intermittent failures between dependent scripts due to timing issues.
Up until now, template authors have had to rely on manual coordination methods (for example, touching a file upon completion).
The goal of startup script coordination is to provide a single reliable source of truth for coordination between workspace startup scripts.

## Quick Start

To start using workspace startup coordination, add calls to `coder exp sync (start|complete)` in your startup scripts where required:

  ```sh
  trap 'coder exp sync complete my-script' EXIT
  coder exp sync want my-script my-other-script
  coder exp sync start my-script
  # Existing startup logic
  ```

For more information, refer to the [usage documentation](./usage.md), [troubleshooting documentation](./troubleshooting.md), or view our [examples](./example.md).

---

# Workspace startup coordination usage

Source: https://coder.com/docs/admin/templates/startup-coordination/usage

> [!NOTE]
> This feature is experimental and may change without notice in future releases.

Startup coordination is built around the concept of **units**. You declare units in your Coder workspace template using the `coder exp sync` command in `coder_script` resources. When the Coder agent starts, it keeps an in-memory directed acyclic graph (DAG) of all units of which it is aware. When you need to synchronize with another unit, you can use `coder exp sync start $UNIT_NAME` to block until all dependencies of that unit have been marked complete.

## What is a unit?

A **unit** is a named phase of work, typically corresponding to a script or initialization
task.

- Units **may** declare dependencies on other units, creating an explicit ordering for workspace initialization.
- Units **must** be registered before they can be marked as complete.
- Units **may** be marked as dependencies before they are registered.
- Units **must not** declare cyclic dependencies. Attempting to create a cyclic dependency will result in an error.

## Requirements

> [!IMPORTANT]
> The `coder exp sync` command is only available from Coder version >=v2.30 onwards.

To use startup dependencies in your templates, you must:

- Modify your workspace startup scripts to run in parallel
- Declare dependencies as required using `coder exp sync`

### Declare Dependencies in your Workspace Startup Scripts

<div class="tabs">

#### Single Dependency

Here's a simple example of a script that depends on another unit completing
first:

```sh
#!/bin/bash
UNIT_NAME="my-setup"

# Declare dependency on git-clone
coder exp sync want "$UNIT_NAME" "git-clone"

# Wait for dependencies and mark as started
coder exp sync start "$UNIT_NAME"

# Do your work here
echo "Running after git-clone completes"

# Signal completion
coder exp sync complete "$UNIT_NAME"
```

This script will wait until the `git-clone` unit completes before starting its
own work.

#### Multiple Dependencies

If your unit depends on multiple other units, you can declare all dependencies
before starting:

```sh
#!/bin/bash
UNIT_NAME="my-app"
DEPENDENCIES="git-clone,env-setup,database-migration"

# Declare all dependencies
if [ -n "$DEPENDENCIES" ]; then
  IFS=',' read -ra DEPS <<< "$DEPENDENCIES"
  for dep in "${DEPS[@]}"; do
    dep=$(echo "$dep" | xargs)  # Trim whitespace
    if [ -n "$dep" ]; then
      coder exp sync want "$UNIT_NAME" "$dep"
    fi
  done
fi

# Wait for all dependencies
coder exp sync start "$UNIT_NAME"

# Your work here
echo "All dependencies satisfied, starting application"

# Signal completion
coder exp sync complete "$UNIT_NAME"
```

</div>

## Inspect Unit State

Use `coder exp sync list` to see all registered units and their current state:

```sh
coder exp sync list
```

Example output:

```sh
UNIT           STATUS     READY
git-clone      completed  true
env-setup      started    true
ide-configure  pending    false
```

To inspect a single unit and its dependencies in detail, use `coder exp sync status <unit>`.

To verify the agent socket is reachable, use `coder exp sync ping`.

## Best Practices

### Test your changes before rolling out to all users

Before rolling out to all users:

1. Create a test workspace from the updated template
2. Check workspace build logs for sync messages
3. Verify all units reach "completed" status using `coder exp sync list`
4. Test workspace functionality

Once you're satisfied, [promote the new template version](../../../reference/cli/templates/versions/promote.md).

### Handle missing CLI gracefully

Not all workspaces will have the Coder CLI available in `$PATH`. Check for availability of the Coder CLI before using
sync commands:

```sh
if command -v coder > /dev/null 2>&1; then
  coder exp sync start "$UNIT_NAME"
else
  echo "Coder CLI not available, continuing without coordination"
fi
```

### Complete units that start successfully

Units **must** call `coder exp sync complete` to unblock dependent units. Use `trap` to ensure
completion even if your script exits early or encounters errors:

```sh

SYNC_STARTED=0
if coder exp sync start "$UNIT_NAME"; then
  SYNC_STARTED=1
fi

cleanup_sync() {
  if [ "$SYNC_STARTED" -eq 1 ]; then
    coder exp sync complete "$UNIT_NAME"
  fi
}
trap cleanup_sync EXIT
```

### Use descriptive unit names

Names should explain what the unit does, not its position in a sequence:

- Good: `git-clone`, `env-setup`, `database-migration`
- Avoid: `step1`, `init`, `script-1`

### Prefix a unique name to your units

When using `coder exp sync` in modules, note that unit names like `git-clone` might be common. Prefix the name of your module to your units to
ensure that your unit does not conflict with others.

- Good: `<module>.git-clone`, `<module>.claude`
- Bad: `git-clone`, `claude`

### Document dependencies

Add comments explaining why dependencies exist:

```tf
resource "coder_script" "ide_setup" {
  # Depends on git-clone because we need .vscode/extensions.json
  # Depends on env-setup because we need $NODE_PATH configured
  script = <<-EOT
    coder exp sync want "ide-setup" "git-clone"
    coder exp sync want "ide-setup" "env-setup"
    # ...
  EOT
}
```

### Avoid circular dependencies

The Coder Agent detects and rejects circular dependencies, but they indicate a design problem:

```sh
# This will fail
coder exp sync want "unit-a" "unit-b"
coder exp sync want "unit-b" "unit-a"
```

## Frequently Asked Questions

### How do I identify scripts that can benefit from startup coordination?

Look for these patterns in existing templates:

- `sleep` commands used to order scripts
- Using files to coordinate startup between scripts (e.g. `touch /tmp/startup-complete`)
- Scripts that fail intermittently on startup
- Comments like "must run after X" or "wait for Y"

### Will this slow down my workspace?

No.
The socket server adds minimal overhead, and the default polling interval is 1&nbsp;second, so waiting for dependencies adds at most a few seconds to startup.
You are more likely to notice an improvement in startup times as it becomes easier to manage complex dependencies in parallel.

### How do units interact with each other?

Units with no dependencies run immediately and in parallel.
Only units with unsatisfied dependencies wait for their dependencies.

### How long can a dependency take to complete?

By default, `coder exp sync start` has a 5-minute timeout to prevent indefinite hangs.
Upon timeout, the command will exit with an error code and print `timeout waiting for dependencies of unit <unit_name>` to stderr.

You can adjust this timeout as necessary for long-running operations:

```sh
coder exp sync start "long-operation" --timeout 10m
```

### Is state stored between restarts?

No. Sync state is kept in-memory only and resets on workspace restart.
This is intentional to ensure clean initialization on every start.

---

# Workspace startup coordination troubleshooting

Source: https://coder.com/docs/admin/templates/startup-coordination/troubleshooting

> [!NOTE]
> This feature is experimental and may change without notice in future releases.

## Test Sync Availability

From a workspace terminal, test if sync is working using `coder exp sync ping`:

```sh
coder exp sync ping
```

* If sync is working, expect the output to be `Success`.
* Otherwise, you will see an error message similar to the below:

```sh
error: connect to agent socket: connect to socket: dial unix /tmp/coder-agent.sock: connect: permission denied
```

## Check Unit Status

You can check the status of a specific unit using `coder exp sync status`:

```sh
coder exp sync status git-clone
```

If the unit exists, you will see output similar to the below:

```sh
# coder exp sync status git-clone
Unit: git-clone
Status: completed
Ready: true
```

If the unit is not known to the agent, you will see output similar to the below:

```sh
# coder exp sync status doesnotexist
Unit: doesnotexist
Status: not registered
Ready: true

Dependencies:
No dependencies found
```

## List All Units

If you are unsure which units are registered, or want a quick overview of every unit's state, use `coder exp sync list`:

```sh
coder exp sync list
```

This displays all registered units, their statuses, and whether they are ready to start:

```sh
UNIT           STATUS     READY
git-clone      completed  true
env-setup      started    true
ide-configure  pending    false
```

You can also get JSON output for scripting:

```sh
coder exp sync list --output json
```

## Common Issues

### Workspace startup script hangs

If the workspace startup scripts appear to 'hang', one or more of your startup scripts may be waiting for a dependency that never completes.

* Inside the workspace, review `/tmp/coder-script-*.log` for more details on your script's execution.
    > **Tip:** add `set -x` to the top of your script to enable debug mode and update/restart the workspace.
* Review your template and verify that `coder exp sync complete <unit>` is called after the script completes e.g. with an exit trap.
* List all units to identify which ones are blocked: `coder exp sync list`.
* View the unit status using `coder exp sync status <unit>`.

### Workspace startup scripts fail

If the workspace startup scripts fail:

* Review `/tmp/coder-script-*.log` inside the workspace for script errors.
* Verify the Coder CLI is available in `$PATH` inside the workspace:

    ```sh
    command -v coder
    ```

### Cycle detected

If you see an error similar to the below in your startup script logs, you have defined a cyclic dependency:

```sh
error: declare dependency failed: cannot add dependency: adding edge for unit "bar": failed to add dependency
adding edge (bar -> foo): cycle detected
```

To fix this, review your dependency declarations and redesign them to remove the cycle. It may help to draw out the dependency graph to find
the cycle.

---

# Workspace startup coordination examples

Source: https://coder.com/docs/admin/templates/startup-coordination/example

## Script Example

This example shows a complete, production-ready script that starts Claude Code
only after a repository has been cloned. It includes error handling, graceful
degradation, and cleanup on exit:

```sh
#!/bin/bash
set -euo pipefail

UNIT_NAME="claude-code"
DEPENDENCIES="git-clone"
REPO_DIR="/workspace/repo"

# Track if sync started successfully
SYNC_STARTED=0

# Declare dependencies
if [ -n "$DEPENDENCIES" ]; then
  if command -v coder > /dev/null 2>&1; then
    IFS=',' read -ra DEPS <<< "$DEPENDENCIES"
    for dep in "${DEPS[@]}"; do
      dep=$(echo "$dep" | xargs)
      if [ -n "$dep" ]; then
        echo "Waiting for dependency: $dep"
        coder exp sync want "$UNIT_NAME" "$dep" > /dev/null 2>&1 || \
          echo "Warning: Failed to register dependency $dep, continuing..."
      fi
    done
  else
    echo "Coder CLI not found, running without sync coordination"
  fi
fi

# Start sync and track success
if [ -n "$UNIT_NAME" ]; then
  if command -v coder > /dev/null 2>&1; then
    if coder exp sync start "$UNIT_NAME" > /dev/null 2>&1; then
      SYNC_STARTED=1
      echo "Started sync: $UNIT_NAME"
    else
      echo "Sync start failed or not available, continuing without sync..."
    fi
  fi
fi

# Ensure completion on exit (even if script fails)
cleanup_sync() {
  if [ "$SYNC_STARTED" -eq 1 ] && [ -n "$UNIT_NAME" ]; then
    echo "Completing sync: $UNIT_NAME"
    coder exp sync complete "$UNIT_NAME" > /dev/null 2>&1 || \
      echo "Warning: Sync complete failed, but continuing..."
  fi
}
trap cleanup_sync EXIT

# Now do the actual work
echo "Repository cloned, starting Claude Code"
cd "$REPO_DIR"
claude
```

This script demonstrates several [best practices](./usage.md#best-practices):

- Checking for Coder CLI availability before using sync commands
- Tracking whether `coder exp sync` started successfully
- Using `trap` to ensure completion even if the script exits early
- Graceful degradation when `coder exp sync` isn't available
- Redirecting `coder exp sync` output to reduce noise in logs

## Template Migration Example

Below is a simple example Docker template that clones [Miguel Grinberg's example Flask repo](https://github.com/miguelgrinberg/microblog/) using the [`git-clone` module](https://registry.coder.com/modules/coder/git-clone) and installs the required dependencies for the project:

- Python development headers (required for building some Python packages)
- Python dependencies from the project's `requirements.txt`

We've omitted some details (such as persistent storage) for brevity, but these are easily added.

### Before

```tf
data "coder_provisioner" "me" {}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}

resource "docker_container" "workspace" {
  count = data.coder_workspace.me.start_count
  image = "codercom/example-base:ubuntu"
  name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
  entrypoint = ["sh", "-c", coder_agent.main.init_script]
  env        = [
    "CODER_AGENT_TOKEN=${coder_agent.main.token}",
    ]
}

resource "coder_agent" "main" {
  arch           = data.coder_provisioner.me.arch
  os             = "linux"
}

module "git-clone" {
  count             = data.coder_workspace.me.start_count
  source            = "registry.coder.com/coder/git-clone/coder"
  version           = "1.2.3"
  agent_id          = coder_agent.main.id
  url               = "https://github.com/miguelgrinberg/microblog"
}

resource "coder_script" "setup" {
  count              = data.coder_workspace.me.start_count
  agent_id           = coder_agent.main.id
  display_name       = "Installing Dependencies"
  run_on_start       = true
  script             = <<EOT
    sudo apt-get update
    sudo apt-get install --yes python-dev-is-python3
    cd ${module.git-clone[count.index].repo_dir}
    python3 -m venv .venv
    source .venv/bin/activate
    pip install -r requirements.txt
  EOT
}
```

We can note the following issues in the above template:

1. There is a race between cloning the repository and the `pip install` commands, which can lead to failed workspace startups in some cases.
2. The `apt` commands can run independently of the `git clone` command, meaning that there is a potential speedup here.

Based on the above, we can improve both the startup time and reliability of the template by splitting the monolithic startup script into multiple independent scripts:

- Install `apt` dependencies
- Install `pip` dependencies (depends on the `git-clone` module and the above step)

### After

Here is the updated version of the template:

```tf
data "coder_provisioner" "me" {}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}

resource "docker_container" "workspace" {
  count = data.coder_workspace.me.start_count
  image = "codercom/example-base:ubuntu"
  name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
  entrypoint = ["sh", "-c", coder_agent.main.init_script]
  env        = [
    "CODER_AGENT_TOKEN=${coder_agent.main.token}",
    ]
}

resource "coder_agent" "main" {
  arch           = data.coder_provisioner.me.arch
  os             = "linux"
}

module "git-clone" {
  count             = data.coder_workspace.me.start_count
  source            = "registry.coder.com/coder/git-clone/coder"
  version           = "1.2.3"
  agent_id          = coder_agent.main.id
  url               = "https://github.com/miguelgrinberg/microblog/"
  post_clone_script = <<-EOT
    coder exp sync start git-clone && coder exp sync complete git-clone
  EOT
}

resource "coder_script" "apt-install" {
  count              = data.coder_workspace.me.start_count
  agent_id           = coder_agent.main.id
  display_name       = "Installing APT Dependencies"
  run_on_start       = true
  script             = <<EOT
    trap 'coder exp sync complete apt-install' EXIT
    coder exp sync start apt-install

    sudo apt-get update
    sudo apt-get install --yes python-dev-is-python3
  EOT
}

resource "coder_script" "pip-install" {
  count              = data.coder_workspace.me.start_count
  agent_id           = coder_agent.main.id
  display_name       = "Installing Python Dependencies"
  run_on_start       = true
  script             = <<EOT
    trap 'coder exp sync complete pip-install' EXIT
    coder exp sync want pip-install git-clone apt-install
    coder exp sync start pip-install

    cd ${module.git-clone[count.index].repo_dir}
    python3 -m venv .venv
    source .venv/bin/activate
    pip install -r requirements.txt
  EOT
}
```

A short summary of the changes:

- We've broken the monolithic "setup" script into two separate scripts: one for the `apt` commands, and one for the `pip` commands.
  - In each script, we've added a `coder exp sync start $SCRIPT_NAME` command to mark the startup script as started.
  - We've also added an exit trap to ensure that we mark the startup scripts as completed. Without this, the `coder exp sync wait` command would eventually time out.
- We have used the `post_clone_script` feature of the `git-clone` module to allow waiting on the Git repository clone.
- In the `pip-install` script, we have declared a dependency on both `git-clone` and `apt-install`.

With these changes, the startup time has been reduced significantly and there is no longer any possibility of a race condition.

---

# Open in Coder

Source: https://coder.com/docs/admin/templates/open-in-coder

You can embed an "Open in Coder" button into your git repos or internal wikis to
let developers quickly launch a new workspace.

<video autoplay playsinline loop>
  <source src="../../images/templates/open-in-coder.mp4?raw=true" type="video/mp4">
Your browser does not support the video tag.
</video>

## How it works

To support any infrastructure and software stack, Coder provides a generic
approach for "Open in Coder" flows.

### 1. Set up git authentication

See [External Authentication](../external-auth/index.md) to set up Git authentication
in your Coder deployment.

### 2. Modify your template to auto-clone repos

The id in the template's `coder_external_auth` data source must match the
`CODER_EXTERNAL_AUTH_X_ID` in the Coder deployment configuration.

If you want the template to clone a specific git repo:

```tf
# Require external authentication to use this template
data "coder_external_auth" "github" {
    id = "primary-github"
}

resource "coder_agent" "dev" {
    # ...
    dir = "~/coder"
    startup_script =<<EOF

    # Clone repo from GitHub
    if [ ! -d "coder" ]
    then
        git clone https://github.com/coder/coder
    fi

    EOF
}
```

> [!NOTE]
> The `dir` attribute can be set in multiple ways, for example:
>
> - `~/coder`
> - `/home/coder/coder`
> - `coder` (relative to the home directory)

If you want the template to support any repository via
[parameters](./extending-templates/parameters.md)

```tf
# Require external authentication to use this template
data "coder_external_auth" "github" {
    id = "primary-github"
}

# Prompt the user for the git repo URL
data "coder_parameter" "git_repo" {
    name          = "git_repo"
    display_name  = "Git repository"
    default       = "https://github.com/coder/coder"
}

locals {
    folder_name = try(element(split("/", data.coder_parameter.git_repo.value), length(split("/", data.coder_parameter.git_repo.value)) - 1), "")
}

resource "coder_agent" "dev" {
    # ...
    dir = "~/${local.folder_name}"
    startup_script =<<EOF

    # Clone repo from GitHub
    if [ ! -d "${local.folder_name}" ]
    then
        git clone ${data.coder_parameter.git_repo.value}
    fi

    EOF
}
```

### 3. Embed the "Open in Coder" button with Markdown

```md
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace)
```

Be sure to replace `YOUR_ACCESS_URL` with your Coder access url (e.g.
<https://coder.example.com>) and `YOUR_TEMPLATE` with the name of your template.

### 4. Optional: pre-fill parameter values in the "Create Workspace" page

This can be used to pre-fill the git repo URL, disk size, image, etc.

```md
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace?param.git_repo=https://github.com/coder/slog&param.home_disk_size%20%28GB%29=20)
```

![Pre-filled parameters](../../images/templates/pre-filled-parameters.png)

### 5. Optional: disable specific parameter fields by including their names as

specified in your template in the `disable_params` search params list

```md
[![Open in Coder](https://YOUR_ACCESS_URL/open-in-coder.svg)](https://YOUR_ACCESS_URL/templates/YOUR_TEMPLATE/workspace?disable_params=first_parameter,second_parameter)
```

### Security: consent dialog for automatic creation

When using `mode=auto` with prefilled `param.*` values, Coder displays a
security consent dialog before creating the workspace. This protects users
from malicious links that could provision workspaces with untrusted
configurations, such as dotfiles or startup scripts from unknown sources.

The dialog shows:

- A warning that a workspace is about to be created automatically from a link
- All prefilled `param.*` values from the URL
- **Confirm and Create** and **Cancel** buttons

The workspace is only created if the user explicitly selects **Confirm and Create**.
Selecting **Cancel** falls back to the standard creation form where all parameters can be reviewed manually.

![Consent dialog for automatic workspace creation](../../images/templates/auto-create-consent-dialog.png)

### Example: Kubernetes

For a full example of the Open in Coder flow in Kubernetes, check out
[this example template](https://github.com/bpmct/coder-templates/tree/main/kubernetes-open-in-coder).

---

# Permissions

Source: https://coder.com/docs/admin/templates/template-permissions

> [!NOTE]
> Template permissions are a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Licensed Coder administrators can control who can use and modify the template.

![Template Permissions](../../images/templates/permissions.png)

Permissions allow you to control who can use and modify the template. Both
individual user and groups can be added to the access list for a template.
Members can be assigned either a `Use` role, granting use of the template to
create workspaces, or `Admin`, allowing a user or members of a group to control
all aspects of the template. This offers a way to elevate the privileges of
ordinary users for specific templates without granting them the site-wide role
of `Template Admin`.

By default the `Everyone` group is assigned to each template meaning any Coder
user can use the template to create a workspace. This access can be revoked
via the actions menu button to the right hand side of each group entry.

> [!WARNING]
> If a user's only access to a template is through a group and they lose that
> access (for example, by being removed from the group or by removing the group
> from the template's permissions), they cannot start or stop workspaces created
> from that template.

---

# Troubleshoot templates

Source: https://coder.com/docs/admin/templates/troubleshooting

Occasionally, you may run into scenarios where a workspace is created, but the
agent is either not connected or the
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script-1)
has failed or timed out.

## Agent connection issues

If the agent is not connected, it means the agent or
[init script](../../../provisionersdk/scripts)
has failed on the resource.

```console
$ coder ssh myworkspace
⢄⡱ Waiting for connection from [agent]...
```

While troubleshooting steps vary by resource, here are some general best
practices:

- Ensure the resource has `curl` installed (alternatively, `wget` or `busybox`)
- Ensure the resource can `curl` your Coder
  [access URL](../../admin/setup/index.md#access-url)
- Manually connect to the resource and check the agent logs (e.g.,
  `kubectl exec`, `docker exec` or AWS console)
  - The Coder agent logs are typically stored in `/tmp/coder-agent.log`
  - The Coder agent startup script logs are typically stored in
    `/tmp/coder-startup-script.log`
  - The Coder agent shutdown script logs are typically stored in
    `/tmp/coder-shutdown-script.log`
- This can also happen if the websockets are not being forwarded correctly when
  running Coder behind a reverse proxy.
  [Read our reverse-proxy docs](../../admin/setup/index.md#tls--reverse-proxy)

## Startup script issues

Depending on the contents of the
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script-1),
and whether or not the
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior-1)
is set to blocking or non-blocking, you may notice issues related to the startup
script. In this section we will cover common scenarios and how to resolve them.

### Unable to access workspace, startup script is still running

If you're trying to access your workspace and are unable to because the
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script-1)
is still running, it means the
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior-1)
option is set to blocking or you have enabled the `--wait=yes` option (for e.g.
`coder ssh` or `coder config-ssh`). In such an event, you can always access the
workspace by using the web terminal, or via SSH using the `--wait=no` option. If
the startup script is running longer than it should, or never completing, you
can try to [debug the startup script](#debug-the-startup-script) to resolve
the issue. Alternatively, you can try to force the startup script to exit by
terminating processes started by it or terminating the startup script itself (on
Linux, `ps` and `kill` are useful tools).

For tips on how to write a startup script that doesn't run forever, see the
[`startup_script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script-1)
section. For more ways to override the startup script behavior, see the
[`startup_script_behavior`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior-1)
section.

Template authors can also set the
[startup script behavior](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script_behavior-1)
option to non-blocking, which will allow users to access the workspace while the
startup script is still running. Note that the workspace must be updated after
changing this option.

### Your workspace may be incomplete

If you see a warning that your workspace may be incomplete, it means you should
be aware that programs, files, or settings may be missing from your workspace.
This can happen if the
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script-1)
is still running or has exited with a non-zero status (see
[startup script error](#startup-script-exited-with-an-error)). No action is
necessary, but you may want to
[start a new shell session](#session-was-started-before-the-startup-script-finished)
after it has completed or check the
[startup script logs](#debug-the-startup-script) to see if there are any
issues.

### Session was started before the startup script finished

The web terminal may show this message if it was started before the
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script-1)
finished, but the startup script has since finished. This message can safely be
dismissed, however, be aware that your preferred shell or dotfiles may not yet
be activated for this shell session. You can either start a new session or
source your dotfiles manually. Note that starting a new session means that
commands running in the terminal will be terminated and you may lose unsaved
work.

Examples for activating your preferred shell or sourcing your dotfiles:

- `exec zsh -l`
- `source ~/.bashrc`

### Startup script exited with an error

When the
[startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script-1)
exits with an error, it means the last command run by the script failed. When
`set -e` is used, this means that any failing command will immediately exit the
script and the remaining commands will not be executed. This also means that
[your workspace may be incomplete](#your-workspace-may-be-incomplete). If you
see this error, you can check the
[startup script logs](#debug-the-startup-script) to figure out what the
issue is.

Common causes for startup script errors:

- A missing command or file
- A command that fails due to missing permissions
- Network issues (e.g., unable to reach a server)

<a id="debugging-the-startup-script"></a>

### Debug the startup script

The simplest way to debug the [startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script-1) is to open the workspace in the Coder dashboard and select "Show startup log" (if not already visible).
This will show all the output from the script. Another
option is to view the log file inside the workspace (usually
`/tmp/coder-startup-script.log`). If the logs don't indicate what's going on or
going wrong, you can increase verbosity by adding `set -x` to the top of the
startup script (note that this will show all commands run and may output
sensitive information). Alternatively, you can add `echo` statements to show
what's going on.

Here's a short example of an informative startup script:

```sh
echo "Running startup script..."
echo "Run: long-running-command"
/path/to/long-running-command
status=$?
echo "Done: long-running-command, exit status: ${status}"
if [ $status -ne 0 ]; then
  echo "Startup script failed, exiting..."
  exit $status
fi
```

> [!NOTE]
> We don't use `set -x` here because we're manually echoing the
> commands. This protects against sensitive information being shown in the log.

This script tells us what command is being run and what the exit status is. If
the exit status is non-zero, it means the command failed and we exit the script.
Since we are manually checking the exit status here, we don't need `set -e` at
the top of the script to exit on error.

> [!NOTE]
> If you aren't seeing any logs, check that the `dir` directive points
> to a valid directory in the file system.

## Slow workspace startup times

If your workspaces are taking longer to start than expected, or longer than
desired, you can diagnose which steps have the highest impact in the workspace
build timings UI (available in v2.17 and beyond). Admins can can
programmatically pull startup times for individual workspace builds using our
[build timings API endpoint](../../reference/api/builds.md#get-workspace-build-timings-by-id).

See our
[guide on optimizing workspace build times](../../tutorials/best-practices/speed-up-templates.md)
to optimize your templates based on this data.

![Workspace build timings UI](../../images/admin/templates/troubleshooting/workspace-build-timings-ui.png)

## Cannot connect to the Docker daemon

If a Docker-based template fails to provision with an error like `Cannot connect to the Docker daemon at unix:///var/run/docker.sock`, the Coder host cannot reach the Docker socket.
Confirm that Docker is installed and running on the host.
If you run Docker through rootless Docker, [Colima](https://colima.run), Podman, or a similar tool, the daemon may expose its socket at a non-default path, so set `DOCKER_HOST` to point at it.
Refer to [Cannot connect to the Docker daemon](../../install/server/docker.md#cannot-connect-to-the-docker-daemon) for the full steps.

## Docker Workspaces on Raspberry Pi OS

### Unable to query ContainerMemory

When you query `ContainerMemory` and encounter the error:

```sh
open /sys/fs/cgroup/memory.max: no such file or directory
```

This error mostly affects Raspberry Pi OS, but might also affect older Debian-based systems as well.

<details><summary>Add cgroup_memory and cgroup_enable to cmdline.txt:</summary>

1. Confirm the list of existing cgroup controllers doesn't include `memory`:

   ```console
   $ cat /sys/fs/cgroup/cgroup.controllers
   cpuset cpu io pids

   $ cat /sys/fs/cgroup/cgroup.subtree_control
   cpuset cpu io pids
   ```

1. Add cgroup entries to `cmdline.txt` in `/boot/firmware` (or `/boot/` on older Pi OS releases):

   ```txt
   cgroup_memory=1 cgroup_enable=memory
   ```

   You can use `sed` to add it to the file for you:

   ```sh
   sudo sed -i '$s/$/ cgroup_memory=1 cgroup_enable=memory/' /boot/firmware/cmdline.txt
   ```

1. Reboot:

   ```sh
   sudo reboot
   ```

1. Confirm that the list of cgroup controllers now includes `memory`:

   ```console
   $ cat /sys/fs/cgroup/cgroup.controllers
   cpuset cpu io memory pids

   $ cat /sys/fs/cgroup/cgroup.subtree_control
   cpuset cpu io memory pids
   ```

Read more about cgroup controllers in [The Linux Kernel](https://docs.kernel.org/admin-guide/cgroup-v2.html#controlling-controllers) documentation.

</details>

---

# External Authentication

Source: https://coder.com/docs/admin/external-auth

Coder supports external authentication via OAuth2.0. This allows enabling any OAuth provider as well as integrations with Git providers,
such as GitHub, GitLab, and Bitbucket.

External authentication can also be used to integrate with external services
like JFrog Artifactory and others.

To add an external authentication provider, you'll need to create an OAuth
application. The following providers have been tested and work with Coder:

- [Azure DevOps](https://learn.microsoft.com/en-us/azure/devops/integrate/get-started/authentication/oauth?view=azure-devops)
- [Azure DevOps (via Entra ID)](https://learn.microsoft.com/en-us/entra/architecture/auth-oauth2)
- [BitBucket](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/)
- [GitHub](#configure-a-github-oauth-app)
- [GitLab](https://docs.gitlab.com/ee/integration/oauth_provider.html)

If you have experience with a provider that is not listed here, please
[file an issue](https://github.com/coder/internal/issues/new?title=request%28docs%29%3A+external-auth+-+request+title+here%0D%0A&labels=["customer-feedback","docs"]&body=doc%3A+%5Bexternal-auth%5D%28https%3A%2F%2Fcoder.com%2Fdocs%2Fadmin%2Fexternal-auth%29%0D%0A%0D%0Aplease+enter+your+request+here%0D%0A)

## Configuration

### Set environment variables

After you create an OAuth application, set environment variables to configure the control plane to use it:

```dotenv
CODER_EXTERNAL_AUTH_0_ID="<USER_DEFINED_ID>"
CODER_EXTERNAL_AUTH_0_TYPE=<github|gitlab|azure-devops|bitbucket-cloud|bitbucket-server|etc>
CODER_EXTERNAL_AUTH_0_CLIENT_ID=<OAuth app client ID>
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=<OAuth app client secret>

# Optionally, configure a custom display name and icon:
CODER_EXTERNAL_AUTH_0_DISPLAY_NAME="Google Calendar"
CODER_EXTERNAL_AUTH_0_DISPLAY_ICON="https://mycustomicon.com/google.svg"
```

The `CODER_EXTERNAL_AUTH_0_ID` environment variable is used as an identifier for the authentication provider.

This variable is used as part of the callback URL path that you must configure in your OAuth provider settings.
If the value in your callback URL doesn't match the `CODER_EXTERNAL_AUTH_0_ID` value, authentication will fail with `redirect URI is not valid`.
Set it with a value that helps you identify the provider.
For example, if you use `CODER_EXTERNAL_AUTH_0_ID="primary-github"` for your GitHub provider,
configure your callback URL as `https://example.com/external-auth/primary-github/callback`.

By default, the redirect URL is built from the access URL Coder is configured
with. You can override the base URL with:

```dotenv
CODER_EXTERNAL_AUTH_0_REDIRECT_URL=https://my.tld
```

This would change the callback in the above example to
`https://my.tld/external-auth/primary-github/callback` (any path component on
the redirect URL is ignored).

Using this setting can break OAuth, so use with caution. The override is
intended to be used when the access URL is internal and either:

- Users access Coder via some other URL that proxies to the internal one.
- The redirect URL redirects to the internal access URL (this can be used to
  work around providers that require public domains for the callback).

Ultimately, the user must end up on the same domain they were on when the
authentication flow was initiated.

### Add an authentication button to the workspace template

Add the following code to any template to add a button to the workspace setup page which will allow you to authenticate with your provider:

```tf
data "coder_external_auth" "<github|gitlab|azure-devops|bitbucket-cloud|bitbucket-server|other>" {
    id = "<USER_DEFINED_ID>"
}

# GitHub Example (CODER_EXTERNAL_AUTH_0_ID="primary-github")
# makes a GitHub authentication token available at data.coder_external_auth.github.access_token
data "coder_external_auth" "github" {
   id = "primary-github"
}

```

Inside your Terraform code, you now have access to authentication variables.
Reference the documentation for your chosen provider for more information on how to supply it with a token.

### Workspace CLI

Use [`external-auth`](../../reference/cli/external-auth/index.md) in the Coder CLI to access a token within the workspace:

```sh
coder external-auth access-token <USER_DEFINED_ID>
```

## Git Authentication in Workspaces

Coder provides automatic Git authentication for workspaces through SSH authentication and Git-provider specific env variables.

When performing Git operations, Coder first attempts to use external auth provider tokens if available.
If no tokens are available, it defaults to SSH authentication.

### OAuth (external auth)

For Git providers configured with [external authentication](#configuration), Coder can use OAuth tokens for Git operations over HTTPS.
When using SSH URLs (like `git@github.com:organization/repo.git`), Coder uses SSH keys as described in the [SSH Authentication](#ssh-authentication) section instead.

For Git operations over HTTPS, Coder automatically injects an external auth provider token.
This works through Git's `GIT_ASKPASS` mechanism, which Coder configures in each workspace.

`GIT_ASKPASS` tells Coder which Git host the operation is for, but never which provider to use.
Coder resolves the provider in two steps:

1. Coder considers only the providers that the workspace's template declares with `data "coder_external_auth"`, and selects the one whose `CODER_EXTERNAL_AUTH_<N>_REGEX` matches the host.
1. If every declared provider is configured and none of them match the host, including when the template declares no providers at all, Coder matches the host against all providers configured on the deployment. This fallback keeps hosts that the template never declares, such as an unrelated Git server, reachable from the workspace.

Because the first step is scoped to the template, two workspaces built from different templates receive their own template's token for the same Git host, regardless of the order the providers appear in the deployment configuration.

To use OAuth tokens for Git authentication over HTTPS:

1. Complete the OAuth authentication flow (**Login with GitHub**, **Login with GitLab**).
1. Use HTTPS URLs when interacting with repositories (`https://github.com/organization/repo.git`).
1. Coder automatically handles authentication. You can perform your Git operations as you normally would.

Behind the scenes, Coder:

- Stores your OAuth token securely in its database
- Sets up `GIT_ASKPASS` at `/tmp/coder.<random-string>/coder` in your workspaces
- Retrieves and injects the appropriate token when Git operations require authentication

To manually access these tokens within a workspace:

```sh
coder external-auth access-token <USER_DEFINED_ID>
```

### SSH Authentication

Coder automatically generates an SSH key pair for each user that can be used for Git operations.
When you use SSH URLs for Git repositories, for example, `git@github.com:organization/repo.git`, Coder checks for and uses an existing SSH key.
If one is not available, it uses the Coder-generated one.

The `coder gitssh` command wraps the standard `ssh` command and injects the SSH key during Git operations.
This works automatically when you:

1. Clone a repository using SSH URLs
1. Pull/push changes to remote repositories
1. Use any Git command that requires SSH authentication

You must add the SSH key to your Git provider.

#### Add your Coder SSH key to your Git provider

1. View your Coder Git SSH key:

   ```sh
   coder publickey
   ```

1. Add the key to your Git provider accounts:

   - [GitHub](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account#adding-a-new-ssh-key-to-your-account)
   - [GitLab](https://docs.gitlab.com/user/ssh/#add-an-ssh-key-to-your-gitlab-account)

## PKCE Support

[PKCE (Proof Key for Code Exchange)](https://datatracker.ietf.org/doc/html/rfc7636) is an OAuth 2.0
security extension that prevents authorization code interception attacks. Coder supports PKCE when
acting as an OAuth client to external identity providers.

Coder will usually assume PKCE support is available with "S256" as the code challenge method. Manual
configuration is available to override any default behavior.

```dotenv
# Enable PKCE with S256 (recommended when supported)
CODER_EXTERNAL_AUTH_0_PKCE_METHODS="S256"

# Disable PKCE entirely
CODER_EXTERNAL_AUTH_0_PKCE_METHODS="none"
```

## Git-provider specific env variables

### Azure DevOps

Azure DevOps requires the following environment variables:

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-azure-devops"
CODER_EXTERNAL_AUTH_0_TYPE=azure-devops
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
# Ensure this value is your "Client Secret", not "App Secret"
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_AUTH_URL="https://app.vssps.visualstudio.com/oauth2/authorize"
CODER_EXTERNAL_AUTH_0_TOKEN_URL="https://app.vssps.visualstudio.com/oauth2/token"
```

### Azure DevOps (via Entra ID)

Azure DevOps (via Entra ID) requires the following environment variables:

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-azure-devops"
CODER_EXTERNAL_AUTH_0_TYPE=azure-devops-entra
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_AUTH_URL="https://login.microsoftonline.com/<TENANT ID>/oauth2/authorize"
```

> [!NOTE]
> Your app registration in Entra ID requires the `vso.code_write` scope

### Bitbucket Server

Bitbucket Server requires the following environment variables:

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-bitbucket-server"
CODER_EXTERNAL_AUTH_0_TYPE=bitbucket-server
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxx
CODER_EXTERNAL_AUTH_0_AUTH_URL=https://bitbucket.example.com/rest/oauth2/latest/authorize
```

When configuring your Bitbucket OAuth application, set the redirect URI to
`https://example.com/external-auth/primary-bitbucket-server/callback`.
This callback path includes the value of `CODER_EXTERNAL_AUTH_0_ID`.

### Gitea

```dotenv
CODER_EXTERNAL_AUTH_0_ID="gitea"
CODER_EXTERNAL_AUTH_0_TYPE=gitea
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
# If self managed, set the Auth URL to your Gitea instance
CODER_EXTERNAL_AUTH_0_AUTH_URL="https://gitea.com/login/oauth/authorize"
```

The redirect URI for Gitea should be
`https://coder.example.com/external-auth/gitea/callback`.

### GitHub

Use this section as a reference for environment variables to customize your setup
or to integrate with an existing GitHub authentication.

For a more complete, step-by-step guide, follow the
[configure a GitHub OAuth app](#configure-a-github-oauth-app) section instead.

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-github"
CODER_EXTERNAL_AUTH_0_TYPE=github
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_REVOKE_URL=https://api.github.com/applications/<CLIENT ID>/grant
```

When configuring your GitHub OAuth application, set the
[authorization callback URL](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/about-the-user-authorization-callback-url)
as `https://example.com/external-auth/primary-github/callback`, where
`primary-github` matches your `CODER_EXTERNAL_AUTH_0_ID` value.

### GitHub Enterprise

GitHub Enterprise requires the following environment variables:

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-github"
CODER_EXTERNAL_AUTH_0_TYPE=github
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_VALIDATE_URL="https://github.example.com/api/v3/user"
CODER_EXTERNAL_AUTH_0_AUTH_URL="https://github.example.com/login/oauth/authorize"
CODER_EXTERNAL_AUTH_0_TOKEN_URL="https://github.example.com/login/oauth/access_token"
```

When configuring your GitHub Enterprise OAuth application, set the
[authorization callback URL](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/about-the-user-authorization-callback-url)
as `https://example.com/external-auth/primary-github/callback`, where
`primary-github` matches your `CODER_EXTERNAL_AUTH_0_ID` value.

### GitLab self-managed

GitLab self-managed requires the following environment variables:

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-gitlab"
CODER_EXTERNAL_AUTH_0_TYPE=gitlab
# This value is the "Application ID"
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_VALIDATE_URL="https://gitlab.example.com/oauth/token/info"
CODER_EXTERNAL_AUTH_0_AUTH_URL="https://gitlab.example.com/oauth/authorize"
CODER_EXTERNAL_AUTH_0_TOKEN_URL="https://gitlab.example.com/oauth/token"
CODER_EXTERNAL_AUTH_0_REVOKE_URL="https://gitlab.example.com/oauth/revoke"
CODER_EXTERNAL_AUTH_0_REGEX=gitlab\.example\.com
```

When [configuring your GitLab OAuth application](https://docs.gitlab.com/17.5/integration/oauth_provider/),
set the redirect URI to `https://example.com/external-auth/primary-gitlab/callback`.
Note that the redirect URI must include the value of `CODER_EXTERNAL_AUTH_0_ID` (in this example, `primary-gitlab`).

### JFrog Artifactory

Visit the [JFrog Artifactory](../../admin/integrations/jfrog-artifactory.md) guide for instructions on how to set up for JFrog Artifactory.

## Self-managed Git providers

Custom authentication and token URLs should be used for self-managed Git
provider deployments.

```dotenv
CODER_EXTERNAL_AUTH_0_AUTH_URL="https://github.example.com/oauth/authorize"
CODER_EXTERNAL_AUTH_0_TOKEN_URL="https://github.example.com/oauth/token"
CODER_EXTERNAL_AUTH_0_REVOKE_URL="https://github.example.com/oauth/revoke"
CODER_EXTERNAL_AUTH_0_VALIDATE_URL="https://example.com/oauth/token/info"
CODER_EXTERNAL_AUTH_0_REGEX=github\.company\.com
```

> [!NOTE]
> The `REGEX` variable must be set if using a custom Git domain.

## Custom scopes

Optionally, you can request custom scopes:

```dotenv
CODER_EXTERNAL_AUTH_0_SCOPES="repo:read repo:write write:gpg_key"
```

## OAuth provider

### Configure a GitHub OAuth app

1. [Create a GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app)

   - Set the authorization callback URL to
     `https://coder.example.com/external-auth/primary-github/callback`, where `primary-github`
     is the value you set for `CODER_EXTERNAL_AUTH_0_ID`.
   - Deactivate Webhooks.
   - Enable fine-grained access to specific repositories or a subset of
     permissions for security.

   ![Register GitHub App](../../images/admin/github-app-register.png)

1. Adjust the GitHub app permissions. You can use more or fewer permissions than
   are listed here, this example allows users to clone
   repositories:

   ![Adjust GitHub App Permissions](../../images/admin/github-app-permissions.png)

   | Name          | Permission   | Description                                            |
   |---------------|--------------|--------------------------------------------------------|
   | Contents      | Read & Write | Grants access to code and commit statuses.             |
   | Pull requests | Read & Write | Grants access to create and update pull requests.      |
   | Workflows     | Read & Write | Grants access to update files in `.github/workflows/`. |
   | Metadata      | Read-only    | Grants access to metadata written by GitHub Apps.      |
   | Members       | Read-only    | Grants access to organization members and teams.       |

1. Install the App for your organization. You may select a subset of
   repositories to grant access to.

   ![Install GitHub App](../../images/admin/github-app-install.png)

1. Make the app installable by other users. In the app's **Advanced**
   tab, select **Make this GitHub App public**.

   Without this, anyone outside the app's owning account or owning
   organization gets a GitHub 404 when they select **Link GitHub** in
   Coder. Each user must also install the app on their own account
   before linking. To surface an **Install GitHub App** link in the
   Coder UI, set the following environment variable:

   ```dotenv
   CODER_EXTERNAL_AUTH_0_APP_INSTALL_URL=https://github.com/apps/<your-app-slug>/installations/new
   ```

## Multiple External Providers (Premium)

> [!NOTE]
> Configuring more than one external authentication provider requires a
> [Premium license](https://coder.com/pricing#compare-plans).
> For more details, [contact your account team](https://coder.com/contact).

Below is an example configuration with multiple providers:

> [!IMPORTANT]
> To support regex matching for paths like `github\.com/org`, add the following `git config` line to the [Coder agent startup script](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script):
>
> ```shell
> git config --global credential.useHttpPath true
> ```

```dotenv
# Provider 1) github.com
CODER_EXTERNAL_AUTH_0_ID=primary-github
CODER_EXTERNAL_AUTH_0_TYPE=github
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_REGEX=github\.com/org

# Provider 2) github.example.com
CODER_EXTERNAL_AUTH_1_ID=secondary-github
CODER_EXTERNAL_AUTH_1_TYPE=github
CODER_EXTERNAL_AUTH_1_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_1_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_1_REGEX=github\.example\.com
CODER_EXTERNAL_AUTH_1_AUTH_URL="https://github.example.com/login/oauth/authorize"
CODER_EXTERNAL_AUTH_1_TOKEN_URL="https://github.example.com/login/oauth/access_token"
CODER_EXTERNAL_AUTH_1_REVOKE_URL="https://github.example.com/login/oauth/revoke"
CODER_EXTERNAL_AUTH_1_VALIDATE_URL="https://github.example.com/api/v3/user"
```

### When Coder can't resolve a single provider

When several providers serve the same Git host, HTTPS Git operations resolve the provider from the workspace template's declared providers, as described in [OAuth (external auth)](#oauth-external-auth).
Coder stops in two cases rather than pick a provider the template didn't ask for.
In both, the request fails and `coder gitaskpass` prints a warning and falls back to Git's own credential behavior, so the Git operation prompts for credentials or fails instead of using an unexpected token.

- **Several of the template's declared providers match the host.**
  Coder can't tell which one the operation needs, so it returns an HTTP 404 naming each match.
  Give the providers non-overlapping `CODER_EXTERNAL_AUTH_<N>_REGEX` values so that only one matches the host, or fetch a token with an explicit provider ID using `coder external-auth access-token <USER_DEFINED_ID>` in your template's startup script.
- **The template declares a provider that the deployment no longer configures, and none of its other declared providers match the host.**
  This happens when a provider is renamed or removed after a template started declaring it.
  Coder returns an HTTP 404 naming the missing provider instead of falling back to a provider the template never declared.
  A provider that the template declares and the deployment still configures keeps serving its own host, so only the hosts that relied on the missing provider are affected.
  Restore that provider's configuration, or update the template to declare a provider that the deployment configures.

---

# Integrations

Source: https://coder.com/docs/admin/integrations

Coder is highly extensible and is not limited to the platforms outlined in these
docs. The control plane can be provisioned on any VM or container compute, and
workspaces can include any Terraform resource. See our
[architecture diagram](../../install/plan/architecture.md) for more details.

You can host your deployment on almost any infrastructure. To learn how, read
our [installation guides](../../install/index.md).

<children></children>

The following resources may help as you're deploying Coder.

- [Coder packages: one-click install on cloud providers](https://github.com/coder/packages)
- [Deploy Coder Air-gapped](../../install/prepare/airgap.md)
- [Supported resources (Terraform registry)](https://registry.terraform.io)
- [Writing custom templates](../templates/index.md)

---

# Prometheus

Source: https://coder.com/docs/admin/integrations/prometheus

Coder exposes many metrics which can be consumed by a Prometheus server, and
give insight into the current state of a live Coder deployment.

If you don't have a Prometheus server installed, you can follow the Prometheus
[Getting started](https://prometheus.io/docs/prometheus/latest/getting_started/) guide.

## Enable Prometheus metrics

Coder server exports metrics via the HTTP endpoint, which can be enabled using
either the environment variable `CODER_PROMETHEUS_ENABLE` or the flag
`--prometheus-enable`.

The Prometheus endpoint address is `http://localhost:2112/` by default. You can
use either the environment variable `CODER_PROMETHEUS_ADDRESS` or the flag
`--prometheus-address <network-interface>:<port>` to select a different listen
address.

If `coder server --prometheus-enable` is started locally, you can preview the
metrics endpoint in your browser or with `curl`:

```console
$ curl http://localhost:2112/
# HELP coderd_api_active_users_duration_hour The number of users that have been active within the last hour.
# TYPE coderd_api_active_users_duration_hour gauge
coderd_api_active_users_duration_hour 0
...
```

### Kubernetes deployment

The Prometheus endpoint can be enabled in the [Helm chart's](../../../helm)
`values.yml` by setting `CODER_PROMETHEUS_ENABLE=true`. Once enabled, the environment variable `CODER_PROMETHEUS_ADDRESS` will be set by default to
`0.0.0.0:2112`. A Service Endpoint will not be exposed; if you need to
expose the Prometheus port on a Service, (for example, to use a
`ServiceMonitor`), create a separate headless service instead.

```yaml
apiVersion: v1
kind: Service
metadata:
  name: coder-prom
  namespace: coder
spec:
  clusterIP: None
  ports:
    - name: prom-http
      port: 2112
      protocol: TCP
      targetPort: 2112
  selector:
    app.kubernetes.io/instance: coder
    app.kubernetes.io/name: coder
  type: ClusterIP
```

### Prometheus configuration

To allow Prometheus to scrape the Coder metrics, you will need to create a
`scrape_config` in your `prometheus.yml` file, or in the Prometheus Helm chart
values. The following is an example `scrape_config`.

```yaml
scrape_configs:
  - job_name: "coder"
    scheme: "http"
    static_configs:
      # replace with the the IP address of the Coder pod or server
      - targets: ["<ip>:2112"]
        labels:
          apps: "coder"
```

If you run a [standalone AI gateway](../../ai-coder/ai-gateway/standalone.md), each replica exports its own metrics on its own listener.
Its Helm chart uses the same `0.0.0.0:2112` default as the `coder` chart, but sets up no scrape discovery.
Refer to [AI gateway monitoring](../../ai-coder/ai-gateway/monitoring.md#kubernetes-discovery) for more details.

To use the Kubernetes Prometheus operator to scrape metrics, you will need to
create a `ServiceMonitor` in your Coder deployment namespace. The following is
an example `ServiceMonitor`.

```yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: coder-service-monitor
  namespace: coder
spec:
  endpoints:
    - port: prom-http
      interval: 10s
      scrapeTimeout: 10s
  namespaceSelector:
    matchNames:
    - coder
  selector:
    matchLabels:
      app.kubernetes.io/name: coder
```

## Available metrics

You must first enable `coderd_agentstats_*` with the flag
`--prometheus-collect-agent-stats`, or the environment variable
`CODER_PROMETHEUS_COLLECT_AGENT_STATS` before they can be retrieved from the
deployment. They will always be available from the agent.

The `coder_ai_gateway_cost_control_*` metrics are exported only by `coderd`.

## Monitor sessions by application

Coder exports session counts and application metadata separately:

- `coderd_agentstats_session_count` reports active sessions by normalized `app_name`, with the other agent identity labels.
- `coderd_agentstats_app_info` reports `app_name`, `family`, and a value of `1` for every registered application, including inactive ones.

Before each execution or dashboard refresh, replace `1790243193` in every info selector with the current Unix time in seconds.
This enriches historical samples without rewriting them; a fixed timestamp freezes metadata, while `@ end()` uses the graph's end time.

To total sessions by family for one deployment, use the same deployment-unique selector on both metrics.
The `job="coder"` selector matches this page's scrape example.

```promql
sum by (family) (
  (
    sum by (app_name) (
      coderd_agentstats_session_count{job="coder"}
    )
      * on (app_name) group_left (family)
        max by (app_name, family) (
          coderd_agentstats_app_info{job="coder"} @ 1790243193
        )
  )
  or
  label_replace(
    sum by (app_name) (
      coderd_agentstats_session_count{job="coder"}
    )
      unless on (app_name)
        max by (app_name) (
          coderd_agentstats_app_info{job="coder"} @ 1790243193
        ),
    "family", "unknown", "", ""
  )
)
```

The fallback assigns `family="unknown"` to unregistered applications and unavailable metadata.

### Query multiple deployments

Coder doesn't export a deployment label.
Attach one to every target and include it in selectors, aggregations, and vector matches.
This example uses `coder_deployment`.

<details><summary>Expand the multi-deployment query</summary>

```promql
sum by (coder_deployment, family) (
  (
    sum by (coder_deployment, app_name) (
      coderd_agentstats_session_count{job="coder", coder_deployment=~".+"}
    )
      * on (coder_deployment, app_name) group_left (family)
        max by (coder_deployment, app_name, family) (
          coderd_agentstats_app_info{job="coder", coder_deployment=~".+"} @ 1790243193
        )
  )
  or
  label_replace(
    sum by (coder_deployment, app_name) (
      coderd_agentstats_session_count{job="coder", coder_deployment=~".+"}
    )
      unless on (coder_deployment, app_name)
        max by (coder_deployment, app_name) (
          coderd_agentstats_app_info{job="coder", coder_deployment=~".+"} @ 1790243193
        ),
    "family", "unknown", "", ""
  )
)
```

</details>

`max` deduplicates identical replica metadata.
Conflicting families for the same deployment and application cause a many-to-many matching error; resolve the replica version mismatch and wait for agreement.

### Plan your series count

- Session gauge: one series per agent and active application, with at most 64 names per report.
  Extra names become `app_name="overflow"`; blank names become `app_name="unknown"`.
- Info gauge: one series per registered application and `coderd` replica.
- Deprecated gauges: four series per agent, whether used or not.

The 64-name cap limits each report, not the deployment total.

### Understand collection behavior

A collection with reports replaces the session gauge, so queries and alerts must tolerate removed series.
A collection without reports retains the previous series.
When identity labels combine agents, Coder keeps `app_name` and sums their values.

### Migrate off the deprecated gauges

The unchanged family-specific gauges count the same sessions as `coderd_agentstats_session_count`.
Querying both counts sessions twice.

<!-- Code generated by 'make docs/admin/integrations/prometheus.md'. DO NOT EDIT -->

| Name                                                                     | Type      | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | Labels                                                                                                |
|--------------------------------------------------------------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------|
| `agent_boundary_log_proxy_batches_dropped_total`                         | counter   | Total number of boundary log batches dropped before reaching coderd. Reason: buffer_full = the agent's internal buffer is full, meaning boundary is producing logs faster than the agent can forward them to coderd; forward_failed = the agent failed to send the batch to coderd, potentially because coderd is unreachable or the connection was interrupted.                                                                                                                                           | `reason`                                                                                              |
| `agent_boundary_log_proxy_batches_forwarded_total`                       | counter   | Total number of boundary log batches successfully forwarded to coderd. Compare with batches_dropped_total to compute a drop rate.                                                                                                                                                                                                                                                                                                                                                                          |                                                                                                       |
| `agent_boundary_log_proxy_logs_dropped_total`                            | counter   | Total number of individual boundary log entries dropped before reaching coderd. Reason: buffer_full = the agent's internal buffer is full; forward_failed = the agent failed to send the batch to coderd; boundary_channel_full = boundary's internal send channel overflowed, meaning boundary is generating logs faster than it can batch and send them; boundary_batch_full = boundary's outgoing batch buffer overflowed after a failed flush, meaning boundary could not write to the agent's socket. | `reason`                                                                                              |
| `agent_scripts_executed_total`                                           | counter   | Total number of scripts executed by the Coder agent. Includes cron scheduled scripts.                                                                                                                                                                                                                                                                                                                                                                                                                      | `agent_name` `success` `template_name` `username` `workspace_name`                                    |
| `coder_ai_gateway_circuit_breaker_rejects_total`                         | counter   | Total number of requests rejected due to open circuit breaker.                                                                                                                                                                                                                                                                                                                                                                                                                                             | `endpoint` `model` `provider`                                                                         |
| `coder_ai_gateway_circuit_breaker_state`                                 | gauge     | Current state of the circuit breaker (0=closed, 0.5=half-open, 1=open).                                                                                                                                                                                                                                                                                                                                                                                                                                    | `endpoint` `model` `provider`                                                                         |
| `coder_ai_gateway_circuit_breaker_trips_total`                           | counter   | Total number of times the circuit breaker transitioned to open state.                                                                                                                                                                                                                                                                                                                                                                                                                                      | `endpoint` `model` `provider`                                                                         |
| `coder_ai_gateway_cost_control_blocked_requests_total`                   | counter   | The number of AI requests blocked because the initiator's budget was exceeded.                                                                                                                                                                                                                                                                                                                                                                                                                             | `group_id`                                                                                            |
| `coder_ai_gateway_cost_control_blocked_users`                            | gauge     | The number of users currently over their AI budget.                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `group_id`                                                                                            |
| `coder_ai_gateway_cost_control_enforcement_duration_seconds`             | histogram | The duration of AI budget enforcement checks, in seconds (outcome: allowed, blocked, error).                                                                                                                                                                                                                                                                                                                                                                                                               | `outcome`                                                                                             |
| `coder_ai_gateway_cost_control_unpriced_token_usage_records_total`       | counter   | The number of recorded AI token-usage records for which no price was found for either the requested model or the provider-reported model. provider is the provider instance name, provider_type is its configured type, model is the requested model, and provider_model is the model reported by the provider (empty when not reported).                                                                                                                                                                  | `model` `provider_model` `provider_type` `provider`                                                   |
| `coder_ai_gateway_injected_tool_invocations_total`                       | counter   | The number of times an injected MCP tool was invoked by AI Gateway.                                                                                                                                                                                                                                                                                                                                                                                                                                        | `model` `name` `provider` `server`                                                                    |
| `coder_ai_gateway_interceptions_duration_seconds`                        | histogram | The total duration of intercepted requests, in seconds. The majority of this time will be the upstream processing of the request. AI Gateway has no control over upstream processing time, so it's just an illustrative metric.                                                                                                                                                                                                                                                                            | `model` `provider`                                                                                    |
| `coder_ai_gateway_interceptions_inflight`                                | gauge     | The number of intercepted requests which are being processed.                                                                                                                                                                                                                                                                                                                                                                                                                                              | `model` `provider` `route`                                                                            |
| `coder_ai_gateway_interceptions_total`                                   | counter   | The count of intercepted requests.                                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `client` `initiator_id` `method` `model` `provider` `route` `status`                                  |
| `coder_ai_gateway_key_pool_exhaustions_total`                            | counter   | The number of times the key pool was exhausted with no usable key (outcome: rate_limited, auth_failed).                                                                                                                                                                                                                                                                                                                                                                                                    | `outcome` `provider`                                                                                  |
| `coder_ai_gateway_key_pool_failover_attempts`                            | histogram | The number of keys attempted before success or exhaustion, per interception for bridged requests and per request for passthrough requests.                                                                                                                                                                                                                                                                                                                                                                 | `provider`                                                                                            |
| `coder_ai_gateway_key_pool_state`                                        | gauge     | The number of keys currently in each state (state: valid, temporary, permanent).                                                                                                                                                                                                                                                                                                                                                                                                                           | `provider` `state`                                                                                    |
| `coder_ai_gateway_key_pool_state_transitions_total`                      | counter   | The number of API key state transitions during failover (reason: rate_limited, unauthorized).                                                                                                                                                                                                                                                                                                                                                                                                              | `provider` `reason`                                                                                   |
| `coder_ai_gateway_non_injected_tool_selections_total`                    | counter   | The number of times an AI model selected a tool to be invoked by the client.                                                                                                                                                                                                                                                                                                                                                                                                                               | `model` `name` `provider`                                                                             |
| `coder_ai_gateway_passthrough_total`                                     | counter   | The count of requests which were not intercepted but passed through to the upstream.                                                                                                                                                                                                                                                                                                                                                                                                                       | `method` `provider` `route`                                                                           |
| `coder_ai_gateway_prompts_total`                                         | counter   | The number of prompts issued by users (initiators).                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `client` `initiator_id` `model` `provider`                                                            |
| `coder_ai_gateway_provider_info`                                         | gauge     | One series per configured AI provider. Value is always 1; the status label (enabled, disabled, error) carries the alertable signal.                                                                                                                                                                                                                                                                                                                                                                        | `provider_name` `provider_type` `status`                                                              |
| `coder_ai_gateway_providers_last_reload_success_timestamp_seconds`       | gauge     | Unix timestamp of the last provider reload that successfully refreshed the providers. A gap against the providers_last_reload_timestamp_seconds gauge means the loop is firing but the refresh function is failing.                                                                                                                                                                                                                                                                                        |                                                                                                       |
| `coder_ai_gateway_providers_last_reload_timestamp_seconds`               | gauge     | Unix timestamp of the last provider reload attempt, success or failure.                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coder_ai_gateway_proxy_connect_sessions_total`                          | counter   | Total number of CONNECT sessions established.                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `type`                                                                                                |
| `coder_ai_gateway_proxy_inflight_mitm_requests`                          | gauge     | Number of MITM requests currently being processed.                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `provider`                                                                                            |
| `coder_ai_gateway_proxy_mitm_requests_total`                             | counter   | Total number of MITM requests handled by the proxy.                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `provider`                                                                                            |
| `coder_ai_gateway_proxy_mitm_responses_total`                            | counter   | Total number of MITM responses by HTTP status code class.                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `code` `provider`                                                                                     |
| `coder_ai_gateway_proxy_provider_info`                                   | gauge     | One series per configured AI provider. Value is always 1; the status label (enabled, disabled, error, proxy_excluded) carries the alertable signal.                                                                                                                                                                                                                                                                                                                                                        | `provider_name` `provider_type` `status`                                                              |
| `coder_ai_gateway_proxy_providers_last_reload_success_timestamp_seconds` | gauge     | Unix timestamp of the last provider reload that successfully refreshed the router. A gap against the providers_last_reload_timestamp_seconds gauge means the loop is firing but the refresh function is failing.                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `coder_ai_gateway_proxy_providers_last_reload_timestamp_seconds`         | gauge     | Unix timestamp of the last provider reload attempt, success or failure.                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coder_ai_gateway_tokens_total`                                          | counter   | The number of tokens used by intercepted requests.                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `client` `initiator_id` `model` `provider` `type`                                                     |
| `coder_derp_server_accepts_total`                                        | counter   | Total DERP connections accepted.                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `coder_derp_server_average_queue_duration_ms`                            | gauge     | Average queue duration in milliseconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coder_derp_server_bytes_received_total`                                 | counter   | Total bytes received.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                                       |
| `coder_derp_server_bytes_sent_total`                                     | counter   | Total bytes sent.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |                                                                                                       |
| `coder_derp_server_clients`                                              | gauge     | Total clients (local + remote).                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `coder_derp_server_clients_local`                                        | gauge     | Local clients.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |                                                                                                       |
| `coder_derp_server_clients_remote`                                       | gauge     | Remote (mesh) clients.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |                                                                                                       |
| `coder_derp_server_connections`                                          | gauge     | Current DERP connections.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                       |
| `coder_derp_server_got_ping_total`                                       | counter   | Total pings received.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                                       |
| `coder_derp_server_home_connections`                                     | gauge     | Current home DERP connections.                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |                                                                                                       |
| `coder_derp_server_home_moves_in_total`                                  | counter   | Total home moves in.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |                                                                                                       |
| `coder_derp_server_home_moves_out_total`                                 | counter   | Total home moves out.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                                       |
| `coder_derp_server_packets_dropped_reason_total`                         | counter   | Packets dropped by reason.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `reason`                                                                                              |
| `coder_derp_server_packets_dropped_total`                                | counter   | Total packets dropped.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |                                                                                                       |
| `coder_derp_server_packets_dropped_type_total`                           | counter   | Packets dropped by type.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | `type`                                                                                                |
| `coder_derp_server_packets_forwarded_in_total`                           | counter   | Total packets forwarded in from mesh peers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                |                                                                                                       |
| `coder_derp_server_packets_forwarded_out_total`                          | counter   | Total packets forwarded out to mesh peers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |                                                                                                       |
| `coder_derp_server_packets_received_kind_total`                          | counter   | Packets received by kind.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `kind`                                                                                                |
| `coder_derp_server_packets_received_total`                               | counter   | Total packets received.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coder_derp_server_packets_sent_total`                                   | counter   | Total packets sent.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |                                                                                                       |
| `coder_derp_server_peer_gone_disconnected_total`                         | counter   | Total peer gone (disconnected) frames sent.                                                                                                                                                                                                                                                                                                                                                                                                                                                                |                                                                                                       |
| `coder_derp_server_peer_gone_not_here_total`                             | counter   | Total peer gone (not here) frames sent.                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coder_derp_server_sent_pong_total`                                      | counter   | Total pongs sent.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |                                                                                                       |
| `coder_derp_server_unknown_frames_total`                                 | counter   | Total unknown frames received.                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |                                                                                                       |
| `coder_derp_server_watchers`                                             | gauge     | Current watchers.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |                                                                                                       |
| `coder_pubsub_connected`                                                 | gauge     | Whether we are connected (1) or not connected (0) to the backend                                                                                                                                                                                                                                                                                                                                                                                                                                           | `backend`                                                                                             |
| `coder_pubsub_current_events`                                            | gauge     | The current number of pubsub event channels listened for                                                                                                                                                                                                                                                                                                                                                                                                                                                   | `backend`                                                                                             |
| `coder_pubsub_current_subscribers`                                       | gauge     | The current number of active pubsub subscribers                                                                                                                                                                                                                                                                                                                                                                                                                                                            | `backend`                                                                                             |
| `coder_pubsub_disconnections_total`                                      | counter   | Total number of times we disconnected unexpectedly from the backend                                                                                                                                                                                                                                                                                                                                                                                                                                        | `backend`                                                                                             |
| `coder_pubsub_latency_measure_errs_total`                                | counter   | The number of pubsub latency measurement failures                                                                                                                                                                                                                                                                                                                                                                                                                                                          | `backend`                                                                                             |
| `coder_pubsub_latency_measures_total`                                    | counter   | The number of pubsub latency measurements                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `backend`                                                                                             |
| `coder_pubsub_messages_total`                                            | counter   | Total number of messages received                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | `backend` `size`                                                                                      |
| `coder_pubsub_published_bytes_total`                                     | counter   | Total number of bytes successfully published across all publishes                                                                                                                                                                                                                                                                                                                                                                                                                                          | `backend`                                                                                             |
| `coder_pubsub_publishes_total`                                           | counter   | Total number of calls to Publish                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | `backend` `success`                                                                                   |
| `coder_pubsub_receive_duration_seconds`                                  | histogram | The time taken to receive a message from a pubsub event channel                                                                                                                                                                                                                                                                                                                                                                                                                                            | `backend`                                                                                             |
| `coder_pubsub_receive_latency_seconds`                                   | gauge     | The most recent time taken to receive a message from a pubsub event channel. New integrations should prefer the coder_pubsub_receive_duration_seconds histogram.                                                                                                                                                                                                                                                                                                                                           | `backend`                                                                                             |
| `coder_pubsub_received_bytes_total`                                      | counter   | Total number of bytes received across all messages                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `backend`                                                                                             |
| `coder_pubsub_send_duration_seconds`                                     | histogram | The time taken to send a message into a pubsub event channel                                                                                                                                                                                                                                                                                                                                                                                                                                               | `backend`                                                                                             |
| `coder_pubsub_send_latency_seconds`                                      | gauge     | The most recent time taken to send a message into a pubsub event channel. New integrations should prefer the coder_pubsub_send_duration_seconds histogram.                                                                                                                                                                                                                                                                                                                                                 | `backend`                                                                                             |
| `coder_pubsub_subscribes_total`                                          | counter   | Total number of calls to Subscribe/SubscribeWithErr                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `backend` `success`                                                                                   |
| `coder_servertailnet_connections_total`                                  | counter   | Total number of TCP connections made to workspace agents.                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `network`                                                                                             |
| `coder_servertailnet_open_connections`                                   | gauge     | Total number of TCP connections currently open to workspace agents.                                                                                                                                                                                                                                                                                                                                                                                                                                        | `network`                                                                                             |
| `coderd_agentapi_metadata_batch_size`                                    | histogram | Total number of metadata entries in each batch, updated before flushes.                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coderd_agentapi_metadata_batch_utilization`                             | histogram | Number of metadata keys per agent in each batch, updated before flushes.                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                       |
| `coderd_agentapi_metadata_batches_total`                                 | counter   | Total number of metadata batches flushed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `reason`                                                                                              |
| `coderd_agentapi_metadata_dropped_keys_total`                            | counter   | Total number of metadata keys dropped due to capacity limits.                                                                                                                                                                                                                                                                                                                                                                                                                                              |                                                                                                       |
| `coderd_agentapi_metadata_flush_duration_seconds`                        | histogram | Time taken to flush metadata batch to database and pubsub.                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `reason`                                                                                              |
| `coderd_agentapi_metadata_flushed_total`                                 | counter   | Total number of unique metadatas flushed.                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                       |
| `coderd_agentapi_metadata_publish_errors_total`                          | counter   | Total number of metadata batch pubsub publish calls that have resulted in an error.                                                                                                                                                                                                                                                                                                                                                                                                                        |                                                                                                       |
| `coderd_agents_apps`                                                     | gauge     | Agent applications with statuses.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | `agent_name` `app_name` `health` `username` `workspace_name`                                          |
| `coderd_agents_connection_latencies_seconds`                             | gauge     | Agent connection latencies in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | `agent_name` `derp_region` `preferred` `username` `workspace_name`                                    |
| `coderd_agents_connections`                                              | gauge     | Agent connections with statuses.                                                                                                                                                                                                                                                                                                                                                                                                                                                                           | `agent_name` `lifecycle_state` `status` `tailnet_node` `username` `workspace_name`                    |
| `coderd_agents_first_connection_seconds`                                 | histogram | Duration from agent creation to first connection in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                               | `agent_name` `template_name`                                                                          |
| `coderd_agents_up`                                                       | gauge     | The number of active agents per workspace.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `template_name` `template_version` `username` `workspace_name`                                        |
| `coderd_agentstats_app_info`                                             | gauge     | The current family of each registered session app. Value is always 1.                                                                                                                                                                                                                                                                                                                                                                                                                                      | `app_name` `family`                                                                                   |
| `coderd_agentstats_connection_count`                                     | gauge     | The number of established connections by agent                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `agent_name` `username` `workspace_name`                                                              |
| `coderd_agentstats_connection_median_latency_seconds`                    | gauge     | The median agent connection latency                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `agent_name` `username` `workspace_name`                                                              |
| `coderd_agentstats_currently_reachable_peers`                            | gauge     | The number of peers (e.g. clients) that are currently reachable over the encrypted network.                                                                                                                                                                                                                                                                                                                                                                                                                | `agent_name` `connection_type` `template_name` `username` `workspace_name`                            |
| `coderd_agentstats_rx_bytes`                                             | gauge     | Agent Rx bytes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `agent_name` `username` `workspace_name`                                                              |
| `coderd_agentstats_session_count`                                        | gauge     | The number of sessions established by app name                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `agent_name` `app_name` `username` `workspace_name`                                                   |
| `coderd_agentstats_session_count_jetbrains`                              | gauge     | The number of session established by JetBrains                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `agent_name` `username` `workspace_name`                                                              |
| `coderd_agentstats_session_count_reconnecting_pty`                       | gauge     | The number of session established by reconnecting PTY                                                                                                                                                                                                                                                                                                                                                                                                                                                      | `agent_name` `username` `workspace_name`                                                              |
| `coderd_agentstats_session_count_ssh`                                    | gauge     | The number of session established by SSH                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | `agent_name` `username` `workspace_name`                                                              |
| `coderd_agentstats_session_count_vscode`                                 | gauge     | The number of session established by VSCode                                                                                                                                                                                                                                                                                                                                                                                                                                                                | `agent_name` `username` `workspace_name`                                                              |
| `coderd_agentstats_session_counts_overflow_total`                        | counter   | Total number of reported session count entries summed into the overflow app after exceeding the per-report cap.                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `coderd_agentstats_startup_script_seconds`                               | gauge     | The number of seconds the startup script took to execute.                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `agent_name` `success` `template_name` `username` `workspace_name`                                    |
| `coderd_agentstats_tx_bytes`                                             | gauge     | Agent Tx bytes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `agent_name` `username` `workspace_name`                                                              |
| `coderd_api_active_users_duration_hour`                                  | gauge     | The number of users that have been active within the last hour.                                                                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `coderd_api_concurrent_requests`                                         | gauge     | The number of concurrent API requests.                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | `method` `path`                                                                                       |
| `coderd_api_concurrent_websockets`                                       | gauge     | The total number of concurrent API websockets.                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `path`                                                                                                |
| `coderd_api_request_latencies_seconds`                                   | histogram | Latency distribution of requests in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                               | `method` `path`                                                                                       |
| `coderd_api_requests_processed_total`                                    | counter   | The total number of processed API requests                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `code` `method` `path`                                                                                |
| `coderd_api_requests_too_large_total`                                    | counter   | The total number of API requests answered 413, by the reason they were rejected. A sustained rate of reason="request_body" on one route is more often a limit set too tight for a legitimate payload than an attempt to exhaust memory. reason="other" counts 413s raised for reasons unrelated to the size of the request body, such as agent log storage overflow or an archive that is too large once expanded.                                                                                         | `method` `path` `reason`                                                                              |
| `coderd_api_total_user_count`                                            | gauge     | The total number of registered users, partitioned by status.                                                                                                                                                                                                                                                                                                                                                                                                                                               | `status`                                                                                              |
| `coderd_api_websocket_durations_seconds`                                 | histogram | Websocket duration distribution of requests in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                    | `path`                                                                                                |
| `coderd_api_websocket_probes_total`                                      | counter   | WebSocket liveness probe outcomes by route. Compare rate(...{result="ok"}[1m]) against coderd_api_concurrent_websockets to detect unresponsive WebSocket connections.                                                                                                                                                                                                                                                                                                                                      | `path` `result`                                                                                       |
| `coderd_api_workspace_latest_build`                                      | gauge     | The current number of workspace builds by status for all non-deleted workspaces.                                                                                                                                                                                                                                                                                                                                                                                                                           | `status`                                                                                              |
| `coderd_authz_authorize_duration_seconds`                                | histogram | Duration of the 'Authorize' call in seconds. Only counts calls that succeed.                                                                                                                                                                                                                                                                                                                                                                                                                               | `allowed`                                                                                             |
| `coderd_authz_prepare_authorize_duration_seconds`                        | histogram | Duration of the 'PrepareAuthorize' call in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                        |                                                                                                       |
| `coderd_build_info`                                                      | gauge     | Describes the current build/version of the Coder server. Value is always 1.                                                                                                                                                                                                                                                                                                                                                                                                                                | `revision` `version`                                                                                  |
| `coderd_chat_auto_archive_records_archived_total`                        | counter   | Total number of chats archived by the auto-archive job (counting both roots and cascaded children).                                                                                                                                                                                                                                                                                                                                                                                                        |                                                                                                       |
| `coderd_chat_workspace_upload_total`                                     | counter   | Total chat workspace file uploads by HTTP response status.                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `status`                                                                                              |
| `coderd_chatd_agents_active`                                             | gauge     | Deployment-wide number of chats holding a concurrent-agent capacity slot. Every replica reports the same database-derived value; aggregate with max, not sum.                                                                                                                                                                                                                                                                                                                                              | `pool`                                                                                                |
| `coderd_chatd_agents_queued_for_capacity`                                | gauge     | Deployment-wide number of chats waiting for a concurrent-agent capacity slot. Every replica reports the same database-derived value; aggregate with max, not sum.                                                                                                                                                                                                                                                                                                                                          | `pool`                                                                                                |
| `coderd_chatd_chats`                                                     | gauge     | Number of chats being processed, by state.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `state`                                                                                               |
| `coderd_chatd_compaction_total`                                          | counter   | Total compaction outcomes (only recorded when compaction was triggered or failed).                                                                                                                                                                                                                                                                                                                                                                                                                         | `model` `provider` `result`                                                                           |
| `coderd_chatd_find_tools_activations_total`                              | counter   | Total deferred tool activations returned by find_tools.                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coderd_chatd_find_tools_calls_total`                                    | counter   | Total find_tools calls.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coderd_chatd_find_tools_empty_total`                                    | counter   | Total find_tools calls with no matches.                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coderd_chatd_find_tools_match_count`                                    | histogram | Number of matches returned by find_tools calls.                                                                                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `coderd_chatd_hook_context_size_bytes`                                   | histogram | Lifecycle hook model context response size in bytes.                                                                                                                                                                                                                                                                                                                                                                                                                                                       | `event`                                                                                               |
| `coderd_chatd_hook_decisions_total`                                      | counter   | Total lifecycle hook permission decisions by event and decision.                                                                                                                                                                                                                                                                                                                                                                                                                                           | `decision` `event`                                                                                    |
| `coderd_chatd_hook_dispatch_seconds`                                     | histogram | Lifecycle hook dispatch duration in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                               | `event`                                                                                               |
| `coderd_chatd_hook_dispatches_total`                                     | counter   | Total lifecycle hook dispatches by event and result.                                                                                                                                                                                                                                                                                                                                                                                                                                                       | `event` `result`                                                                                      |
| `coderd_chatd_hook_input_overrides_total`                                | counter   | Total lifecycle hook input overrides by event.                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `event`                                                                                               |
| `coderd_chatd_message_count`                                             | histogram | Number of messages in the prompt per LLM request.                                                                                                                                                                                                                                                                                                                                                                                                                                                          | `model` `provider`                                                                                    |
| `coderd_chatd_prompt_size_bytes`                                         | histogram | Estimated byte size of the prompt per LLM request.                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `model` `provider`                                                                                    |
| `coderd_chatd_steps_total`                                               | counter   | Total agentic loop steps across all chats.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `model` `provider`                                                                                    |
| `coderd_chatd_stream_retries_total`                                      | counter   | Total LLM stream retries.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `kind` `model` `provider`                                                                             |
| `coderd_chatd_tool_errors_total`                                         | counter   | Total tool calls that returned an error result.                                                                                                                                                                                                                                                                                                                                                                                                                                                            | `model` `provider` `tool_name`                                                                        |
| `coderd_chatd_tool_result_size_bytes`                                    | histogram | Size in bytes of each tool execution result.                                                                                                                                                                                                                                                                                                                                                                                                                                                               | `model` `provider` `tool_name`                                                                        |
| `coderd_chatd_tool_result_truncated_total`                               | counter   | Total tool results truncated to fit the model context window.                                                                                                                                                                                                                                                                                                                                                                                                                                              | `model` `provider` `tool_name`                                                                        |
| `coderd_chatd_ttft_seconds`                                              | histogram | Time-to-first-token: wall time from LLM request to first streamed chunk.                                                                                                                                                                                                                                                                                                                                                                                                                                   | `model` `provider`                                                                                    |
| `coderd_db_query_counts_total`                                           | counter   | Total number of queries labelled by HTTP route, method, and query name.                                                                                                                                                                                                                                                                                                                                                                                                                                    | `method` `query` `route`                                                                              |
| `coderd_db_query_latencies_seconds`                                      | histogram | Latency distribution of queries in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                                | `query`                                                                                               |
| `coderd_db_tx_duration_seconds`                                          | histogram | Duration of transactions in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       | `success` `tx_id`                                                                                     |
| `coderd_db_tx_executions_count`                                          | counter   | Total count of transactions executed. 'retries' is expected to be 0 for a successful transaction.                                                                                                                                                                                                                                                                                                                                                                                                          | `retries` `success` `tx_id`                                                                           |
| `coderd_dbpurge_chat_search_rows_backfilled_total`                       | counter   | Total number of chat message rows whose search_tsv was backfilled.                                                                                                                                                                                                                                                                                                                                                                                                                                         |                                                                                                       |
| `coderd_dbpurge_iteration_duration_seconds`                              | histogram | Duration of each dbpurge iteration in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                             | `success`                                                                                             |
| `coderd_dbpurge_records_purged_total`                                    | counter   | Total number of records purged by type.                                                                                                                                                                                                                                                                                                                                                                                                                                                                    | `record_type`                                                                                         |
| `coderd_experiments`                                                     | gauge     | Indicates whether each experiment is enabled (1) or not (0)                                                                                                                                                                                                                                                                                                                                                                                                                                                | `experiment`                                                                                          |
| `coderd_insights_applications_usage_seconds`                             | gauge     | The application usage per template.                                                                                                                                                                                                                                                                                                                                                                                                                                                                        | `application_name` `organization_name` `slug` `template_name`                                         |
| `coderd_insights_parameters`                                             | gauge     | The parameter usage per template.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | `organization_name` `parameter_name` `parameter_type` `parameter_value` `template_name`               |
| `coderd_insights_templates_active_users`                                 | gauge     | The number of active users of the template.                                                                                                                                                                                                                                                                                                                                                                                                                                                                | `organization_name` `template_name`                                                                   |
| `coderd_license_active_users`                                            | gauge     | The number of active users.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |                                                                                                       |
| `coderd_license_errors`                                                  | gauge     | The number of active license errors.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |                                                                                                       |
| `coderd_license_limit_users`                                             | gauge     | The user seats limit based on the active Coder license.                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coderd_license_user_limit_enabled`                                      | gauge     | Returns 1 if the current license enforces the user limit.                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                       |
| `coderd_license_warnings`                                                | gauge     | The number of active license warnings.                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |                                                                                                       |
| `coderd_lifecycle_autobuild_execution_duration_seconds`                  | histogram | Duration of each autobuild execution.                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                                       |
| `coderd_notifications_dispatcher_send_seconds`                           | histogram | The time taken to dispatch notifications.                                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `method`                                                                                              |
| `coderd_notifications_inflight_dispatches`                               | gauge     | The number of dispatch attempts which are currently in progress.                                                                                                                                                                                                                                                                                                                                                                                                                                           | `method` `notification_template_id`                                                                   |
| `coderd_notifications_pending_updates`                                   | gauge     | The number of dispatch attempt results waiting to be flushed to the store.                                                                                                                                                                                                                                                                                                                                                                                                                                 |                                                                                                       |
| `coderd_notifications_queued_seconds`                                    | histogram | The time elapsed between a notification being enqueued in the store and retrieved for dispatching (measures the latency of the notifications system). This should generally be within CODER_NOTIFICATIONS_FETCH_INTERVAL seconds; higher values for a sustained period indicates delayed processing and CODER_NOTIFICATIONS_LEASE_COUNT can be increased to accommodate this.                                                                                                                              | `method`                                                                                              |
| `coderd_notifications_retry_count`                                       | counter   | The count of notification dispatch retry attempts.                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `method` `notification_template_id`                                                                   |
| `coderd_notifications_synced_updates_total`                              | counter   | The number of dispatch attempt results flushed to the store.                                                                                                                                                                                                                                                                                                                                                                                                                                               |                                                                                                       |
| `coderd_oauth2_external_requests_rate_limit`                             | gauge     | The total number of allowed requests per interval.                                                                                                                                                                                                                                                                                                                                                                                                                                                         | `name` `resource`                                                                                     |
| `coderd_oauth2_external_requests_rate_limit_next_reset_unix`             | gauge     | Unix timestamp for when the next interval starts                                                                                                                                                                                                                                                                                                                                                                                                                                                           | `name` `resource`                                                                                     |
| `coderd_oauth2_external_requests_rate_limit_remaining`                   | gauge     | The remaining number of allowed requests in this interval.                                                                                                                                                                                                                                                                                                                                                                                                                                                 | `name` `resource`                                                                                     |
| `coderd_oauth2_external_requests_rate_limit_reset_in_seconds`            | gauge     | Seconds until the next interval                                                                                                                                                                                                                                                                                                                                                                                                                                                                            | `name` `resource`                                                                                     |
| `coderd_oauth2_external_requests_rate_limit_used`                        | gauge     | The number of requests made in this interval.                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `name` `resource`                                                                                     |
| `coderd_oauth2_external_requests_rate_limited_total`                     | counter   | The total number of api calls to external oauth2 providers that returned a rate-limited response (a 429, or a 403 with rate-limit headers).                                                                                                                                                                                                                                                                                                                                                                | `name` `source` `status_code`                                                                         |
| `coderd_oauth2_external_requests_total`                                  | counter   | The total number of api calls made to external oauth2 providers. 'status_code' will be 0 if the request failed with no response.                                                                                                                                                                                                                                                                                                                                                                           | `name` `source` `status_code`                                                                         |
| `coderd_open_file_refs_current`                                          | gauge     | The count of file references currently open in the file cache. Multiple references can be held for the same file.                                                                                                                                                                                                                                                                                                                                                                                          |                                                                                                       |
| `coderd_open_file_refs_total`                                            | counter   | The total number of file references ever opened in the file cache. The 'hit' label indicates if the file was loaded from the cache.                                                                                                                                                                                                                                                                                                                                                                        | `hit`                                                                                                 |
| `coderd_open_files_current`                                              | gauge     | The count of unique files currently open in the file cache.                                                                                                                                                                                                                                                                                                                                                                                                                                                |                                                                                                       |
| `coderd_open_files_size_bytes_current`                                   | gauge     | The current amount of memory of all files currently open in the file cache.                                                                                                                                                                                                                                                                                                                                                                                                                                |                                                                                                       |
| `coderd_open_files_size_bytes_total`                                     | counter   | The total amount of memory ever opened in the file cache. This number never decrements.                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coderd_open_files_total`                                                | counter   | The total count of unique files ever opened in the file cache.                                                                                                                                                                                                                                                                                                                                                                                                                                             |                                                                                                       |
| `coderd_prebuilds_reconciliation_duration_seconds`                       | histogram | Duration of each prebuilds reconciliation cycle.                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `coderd_prebuilt_workspace_claim_duration_seconds`                       | histogram | Time to claim a prebuilt workspace by organization, template, and preset.                                                                                                                                                                                                                                                                                                                                                                                                                                  | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_claimed_total`                               | counter   | Total number of prebuilt workspaces which were claimed by users. Claiming refers to creating a workspace with a preset selected for which eligible prebuilt workspaces are available and one is reassigned to a user.                                                                                                                                                                                                                                                                                      | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_created_total`                               | counter   | Total number of prebuilt workspaces that have been created to meet the desired instance count of each template preset.                                                                                                                                                                                                                                                                                                                                                                                     | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_desired`                                     | gauge     | Target number of prebuilt workspaces that should be available for each template preset.                                                                                                                                                                                                                                                                                                                                                                                                                    | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_eligible`                                    | gauge     | Current number of prebuilt workspaces that are eligible to be claimed by users. These are workspaces that have completed their build process with their agent reporting 'ready' status.                                                                                                                                                                                                                                                                                                                    | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_failed_total`                                | counter   | Total number of prebuilt workspaces that failed to build.                                                                                                                                                                                                                                                                                                                                                                                                                                                  | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_metrics_last_updated`                        | gauge     | The unix timestamp when the metrics related to prebuilt workspaces were last updated; these metrics are cached.                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `coderd_prebuilt_workspaces_preset_hard_limited`                         | gauge     | Indicates whether a given preset has reached the hard failure limit (1 = hard-limited). Metric is omitted otherwise.                                                                                                                                                                                                                                                                                                                                                                                       | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_preset_validation_failed`                    | gauge     | Indicates whether a given preset has validation failures (1 = validation failed). Metric is omitted otherwise.                                                                                                                                                                                                                                                                                                                                                                                             | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_reconciliation_paused`                       | gauge     | Indicates whether prebuilds reconciliation is currently paused (1 = paused, 0 = not paused).                                                                                                                                                                                                                                                                                                                                                                                                               |                                                                                                       |
| `coderd_prebuilt_workspaces_resource_replacements_total`                 | counter   | Total number of prebuilt workspaces whose resource(s) got replaced upon being claimed. In Terraform, drift on immutable attributes results in resource replacement. This represents a worst-case scenario for prebuilt workspaces because the pre-provisioned resource would have been recreated when claiming, thus obviating the point of pre-provisioning. See https://coder.com/docs/admin/templates/extending-templates/prebuilt-workspaces#preventing-resource-replacement                           | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prebuilt_workspaces_running`                                     | gauge     | Current number of prebuilt workspaces that are in a running state. These workspaces have started successfully but may not yet be claimable by users (see coderd_prebuilt_workspaces_eligible).                                                                                                                                                                                                                                                                                                             | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_prometheusmetrics_agents_execution_seconds`                      | histogram | Histogram for duration of agents metrics collection in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `coderd_prometheusmetrics_agentstats_execution_seconds`                  | histogram | Histogram for duration of agent stats metrics collection in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                       |                                                                                                       |
| `coderd_prometheusmetrics_metrics_aggregator_execution_cleanup_seconds`  | histogram | Histogram for duration of metrics aggregator cleanup in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `coderd_prometheusmetrics_metrics_aggregator_execution_update_seconds`   | histogram | Histogram for duration of metrics aggregator update in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `coderd_prometheusmetrics_metrics_aggregator_store_size`                 | gauge     | The number of metrics stored in the aggregator                                                                                                                                                                                                                                                                                                                                                                                                                                                             |                                                                                                       |
| `coderd_provisioner_job_queue_wait_seconds`                              | histogram | Time from job creation to acquisition by a provisioner daemon.                                                                                                                                                                                                                                                                                                                                                                                                                                             | `build_reason` `job_type` `provisioner_type` `transition`                                             |
| `coderd_provisionerd_job_timings_seconds`                                | histogram | The provisioner job time duration in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                              | `provisioner` `status`                                                                                |
| `coderd_provisionerd_jobs_current`                                       | gauge     | The number of currently running provisioner jobs.                                                                                                                                                                                                                                                                                                                                                                                                                                                          | `provisioner`                                                                                         |
| `coderd_provisionerd_num_daemons`                                        | gauge     | The number of provisioner daemons.                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |                                                                                                       |
| `coderd_provisionerd_workspace_build_timings_seconds`                    | histogram | The time taken for a workspace to build.                                                                                                                                                                                                                                                                                                                                                                                                                                                                   | `status` `template_name` `template_version` `workspace_transition`                                    |
| `coderd_proxyhealth_health_check_duration_seconds`                       | histogram | Histogram for duration of proxy health collection in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                              |                                                                                                       |
| `coderd_proxyhealth_health_check_results`                                | gauge     | This endpoint returns a number to indicate the health status. -3 (unknown), -2 (Unreachable), -1 (Unhealthy), 0 (Unregistered), 1 (Healthy)                                                                                                                                                                                                                                                                                                                                                                | `proxy_id`                                                                                            |
| `coderd_template_workspace_build_duration_seconds`                       | histogram | Duration from workspace build creation to agent ready, by template.                                                                                                                                                                                                                                                                                                                                                                                                                                        | `is_prebuild` `organization_name` `status` `template_name` `transition`                               |
| `coderd_usage_events_expired`                                            | gauge     | Number of unpublished usage events aged 30 to 60 days. Events older than 60 days are not counted.                                                                                                                                                                                                                                                                                                                                                                                                          |                                                                                                       |
| `coderd_usage_events_pending`                                            | gauge     | Number of unpublished usage events within the 30-day publishing window.                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `coderd_usage_events_pending_oldest_age_seconds`                         | gauge     | Age in seconds of the oldest unpublished usage event within the 30-day publishing window. Zero when no events are pending.                                                                                                                                                                                                                                                                                                                                                                                 |                                                                                                       |
| `coderd_usage_events_publish_results_total`                              | counter   | Total usage events accepted or rejected after a valid Tallyman response, by result and event type.                                                                                                                                                                                                                                                                                                                                                                                                         | `event_type` `result`                                                                                 |
| `coderd_usage_events_publish_send_errors_total`                          | counter   | Total usage event publish attempts that did not receive a valid Tallyman response. Does not reset after a valid response.                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                       |
| `coderd_workspace_builds_enqueued_total`                                 | counter   | Total number of workspace build enqueue attempts.                                                                                                                                                                                                                                                                                                                                                                                                                                                          | `build_reason` `provisioner_type` `status` `transition`                                               |
| `coderd_workspace_builds_total`                                          | counter   | The number of workspaces started, updated, or deleted.                                                                                                                                                                                                                                                                                                                                                                                                                                                     | `status` `template_name` `template_version` `workspace_name` `workspace_owner` `workspace_transition` |
| `coderd_workspace_creation_duration_seconds`                             | histogram | Time to create a workspace by organization, template, preset, and type (regular or prebuild).                                                                                                                                                                                                                                                                                                                                                                                                              | `organization_name` `preset_name` `template_name` `type`                                              |
| `coderd_workspace_creation_total`                                        | counter   | Total regular (non-prebuilt) workspace creations by organization, template, and preset.                                                                                                                                                                                                                                                                                                                                                                                                                    | `organization_name` `preset_name` `template_name`                                                     |
| `coderd_workspace_latest_build_status`                                   | gauge     | The current workspace statuses by template, transition, and owner for all non-deleted workspaces.                                                                                                                                                                                                                                                                                                                                                                                                          | `status` `template_name` `template_version` `workspace_owner` `workspace_transition`                  |
| `go_gc_duration_seconds`                                                 | summary   | A summary of the pause duration of garbage collection cycles.                                                                                                                                                                                                                                                                                                                                                                                                                                              |                                                                                                       |
| `go_goroutines`                                                          | gauge     | Number of goroutines that currently exist.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |                                                                                                       |
| `go_info`                                                                | gauge     | Information about the Go environment.                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | `version`                                                                                             |
| `go_memstats_alloc_bytes`                                                | gauge     | Number of bytes allocated and still in use.                                                                                                                                                                                                                                                                                                                                                                                                                                                                |                                                                                                       |
| `go_memstats_alloc_bytes_total`                                          | counter   | Total number of bytes allocated, even if freed.                                                                                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `go_memstats_buck_hash_sys_bytes`                                        | gauge     | Number of bytes used by the profiling bucket hash table.                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                       |
| `go_memstats_frees_total`                                                | counter   | Total number of frees.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |                                                                                                       |
| `go_memstats_gc_sys_bytes`                                               | gauge     | Number of bytes used for garbage collection system metadata.                                                                                                                                                                                                                                                                                                                                                                                                                                               |                                                                                                       |
| `go_memstats_heap_alloc_bytes`                                           | gauge     | Number of heap bytes allocated and still in use.                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `go_memstats_heap_idle_bytes`                                            | gauge     | Number of heap bytes waiting to be used.                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                       |
| `go_memstats_heap_inuse_bytes`                                           | gauge     | Number of heap bytes that are in use.                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                                       |
| `go_memstats_heap_objects`                                               | gauge     | Number of allocated objects.                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |                                                                                                       |
| `go_memstats_heap_released_bytes`                                        | gauge     | Number of heap bytes released to OS.                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |                                                                                                       |
| `go_memstats_heap_sys_bytes`                                             | gauge     | Number of heap bytes obtained from system.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |                                                                                                       |
| `go_memstats_last_gc_time_seconds`                                       | gauge     | Number of seconds since 1970 of last garbage collection.                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                       |
| `go_memstats_lookups_total`                                              | counter   | Total number of pointer lookups.                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `go_memstats_mallocs_total`                                              | counter   | Total number of mallocs.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                       |
| `go_memstats_mcache_inuse_bytes`                                         | gauge     | Number of bytes in use by mcache structures.                                                                                                                                                                                                                                                                                                                                                                                                                                                               |                                                                                                       |
| `go_memstats_mcache_sys_bytes`                                           | gauge     | Number of bytes used for mcache structures obtained from system.                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `go_memstats_mspan_inuse_bytes`                                          | gauge     | Number of bytes in use by mspan structures.                                                                                                                                                                                                                                                                                                                                                                                                                                                                |                                                                                                       |
| `go_memstats_mspan_sys_bytes`                                            | gauge     | Number of bytes used for mspan structures obtained from system.                                                                                                                                                                                                                                                                                                                                                                                                                                            |                                                                                                       |
| `go_memstats_next_gc_bytes`                                              | gauge     | Number of heap bytes when next garbage collection will take place.                                                                                                                                                                                                                                                                                                                                                                                                                                         |                                                                                                       |
| `go_memstats_other_sys_bytes`                                            | gauge     | Number of bytes used for other system allocations.                                                                                                                                                                                                                                                                                                                                                                                                                                                         |                                                                                                       |
| `go_memstats_stack_inuse_bytes`                                          | gauge     | Number of bytes in use by the stack allocator.                                                                                                                                                                                                                                                                                                                                                                                                                                                             |                                                                                                       |
| `go_memstats_stack_sys_bytes`                                            | gauge     | Number of bytes obtained from system for stack allocator.                                                                                                                                                                                                                                                                                                                                                                                                                                                  |                                                                                                       |
| `go_memstats_sys_bytes`                                                  | gauge     | Number of bytes obtained from system.                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |                                                                                                       |
| `go_threads`                                                             | gauge     | Number of OS threads created.                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |                                                                                                       |
| `process_cpu_seconds_total`                                              | counter   | Total user and system CPU time spent in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `process_max_fds`                                                        | gauge     | Maximum number of open file descriptors.                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |                                                                                                       |
| `process_open_fds`                                                       | gauge     | Number of open file descriptors.                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |                                                                                                       |
| `process_resident_memory_bytes`                                          | gauge     | Resident memory size in bytes.                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |                                                                                                       |
| `process_start_time_seconds`                                             | gauge     | Start time of the process since unix epoch in seconds.                                                                                                                                                                                                                                                                                                                                                                                                                                                     |                                                                                                       |
| `process_virtual_memory_bytes`                                           | gauge     | Virtual memory size in bytes.                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |                                                                                                       |
| `process_virtual_memory_max_bytes`                                       | gauge     | Maximum amount of virtual memory available in bytes.                                                                                                                                                                                                                                                                                                                                                                                                                                                       |                                                                                                       |
| `promhttp_metric_handler_requests_in_flight`                             | gauge     | Current number of scrapes being served.                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |                                                                                                       |
| `promhttp_metric_handler_requests_total`                                 | counter   | Total number of scrapes by HTTP status code.                                                                                                                                                                                                                                                                                                                                                                                                                                                               | `code`                                                                                                |

<!-- End generated by 'make docs/admin/integrations/prometheus.md'. -->

### Note on Prometheus native histogram support

The following metrics support native histograms:

- `coderd_workspace_creation_duration_seconds`
- `coderd_prebuilt_workspace_claim_duration_seconds`
- `coderd_template_workspace_build_duration_seconds`
- `coder_pubsub_send_duration_seconds`
- `coder_pubsub_receive_duration_seconds`

Native histograms are an **experimental** Prometheus feature that removes the need to predefine bucket boundaries and allows higher-resolution buckets that adapt to deployment characteristics.
Whether a metric is exposed as classic or native depends entirely on the Prometheus server configuration (see [Prometheus docs](https://prometheus.io/docs/specs/native_histograms/) for details):

- If native histograms are enabled, Prometheus ingests the high-resolution histogram.
- If not, it falls back to the predefined buckets.

⚠️ Important: classic and native histograms cannot be aggregated together. If Prometheus is switched from classic to native at a certain point in time, dashboards may need to account for that transition.
For this reason, it’s recommended to follow [Prometheus’ migration guidelines](https://prometheus.io/docs/specs/native_histograms/#migration-considerations) when moving from classic to native histograms.

---

# Kubernetes event logs

Source: https://coder.com/docs/admin/integrations/kubernetes-logs

To stream Kubernetes events into your workspace startup logs, you can use
Coder's [`coder-logstream-kube`](https://github.com/coder/coder-logstream-kube)
tool. `coder-logstream-kube` provides useful information about the workspace pod
or deployment, such as:

- Causes of pod provisioning failures, or why a pod is stuck in a pending state.
- Visibility into when pods are OOMKilled, or when they are evicted.

## Installation

Install the `coder-logstream-kube` helm chart on the cluster where the
deployment is running.

```sh
helm repo add coder-logstream-kube https://helm.coder.com/logstream-kube
helm install coder-logstream-kube coder-logstream-kube/coder-logstream-kube \
    --namespace coder \
    --set url=<your-coder-url-including-http-or-https>
```

## Example logs

Here is an example of the logs you can expect to see in the workspace startup
logs:

### Normal pod deployment

![normal pod deployment](../../images/admin/integrations/coder-logstream-kube-logs-normal.png)

### Wrong image

![Wrong image name](../../images/admin/integrations/coder-logstream-kube-logs-wrong-image.png)

### Kubernetes quota exceeded

![Kubernetes quota exceeded](../../images/admin/integrations/coder-logstream-kube-logs-quota-exceeded.png)

### Pod crash loop

![Pod crash loop](../../images/admin/integrations/coder-logstream-kube-logs-pod-crashed.png)

## How it works

Kubernetes provides an
[informers](https://pkg.go.dev/k8s.io/client-go/informers) API that streams pod
and event data from the API server.

coder-logstream-kube listens for pod creation events with containers that have
the CODER_AGENT_TOKEN environment variable set. All pod events are streamed as
logs to the Coder API using the agent token for authentication. For more
details, see the
[coder-logstream-kube](https://github.com/coder/coder-logstream-kube)
repository.

---

# Additional clusters

Source: https://coder.com/docs/admin/integrations/multiple-kube-clusters

With Coder, you can deploy workspaces in additional Kubernetes clusters using
different
[authentication methods](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs#authentication)
in the Terraform provider.

![Region picker in "Create Workspace" screen](../../images/admin/integrations/kube-region-picker.png)

## Option 1) Kubernetes contexts and kubeconfig

First, create a kubeconfig file with
[multiple contexts](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/).

```sh
kubectl config get-contexts

CURRENT   NAME                        CLUSTER
          workspaces-europe-west2-c   workspaces-europe-west2-c
*         workspaces-us-central1-a    workspaces-us-central1-a
```

### Kubernetes control plane

If you deployed Coder on Kubernetes, you can attach a kubeconfig as a secret.

This assumes Coder is deployed on the `coder` namespace and your kubeconfig file
is in ~/.kube/config.

```sh
kubectl create secret generic kubeconfig-secret -n coder --from-file=~/.kube/config
```

Modify your helm values to mount the secret:

```yaml
coder:
  # ...
  volumes:
    - name: "kubeconfig-mount"
      secret:
        secretName: "kubeconfig-secret"
  volumeMounts:
    - name: "kubeconfig-mount"
      mountPath: "/mnt/secrets/kube"
      readOnly: true
```

[Upgrade Coder](../../install/server/kubernetes/index.md#upgrade-coder-via-helm) with these
new values.

### VM control plane

If you deployed Coder on a VM, copy the kubeconfig file to
`/home/coder/.kube/config`.

### Create a Coder template

You can start from our
[example template](../../../examples/templates/kubernetes).
From there, add
[template parameters](../templates/extending-templates/parameters.md) to allow
developers to pick their desired cluster.

```tf
# main.tf

data "coder_parameter" "kube_context" {
  name         = "kube_context"
  display_name = "Cluster"
  default      = "workspaces-us-central1-a"
  mutable      = false
  option {
    name  = "US Central"
    icon  = "/emojis/1f33d.png"
    value = "workspaces-us-central1-a"
  }
  option {
    name  = "Europe West"
    icon  = "/emojis/1f482.png"
    value = "workspaces-europe-west2-c"
  }
}

provider "kubernetes" {
  config_path    = "~/.kube/config" # or /mnt/secrets/kube/config for Kubernetes
  config_context = data.coder_parameter.kube_context.value
}
```

## Option 2) Kubernetes ServiceAccounts

Alternatively, you can authenticate with remote clusters with ServiceAccount
tokens. Coder can store these secrets on your behalf with
[managed Terraform variables](../templates/extending-templates/variables.md).

Alternatively, these could also be fetched from Kubernetes secrets or even [HashiCorp Vault](https://registry.terraform.io/providers/hashicorp/vault/latest/docs/data-sources/generic_secret).

This guide assumes you have a `coder-workspaces` namespace on your remote
cluster. Change the namespace accordingly.

### Create a ServiceAccount

Run this command against your remote cluster to create a ServiceAccount, Role,
RoleBinding, and token:

```sh
kubectl apply -n coder-workspaces -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: coder-v2
---
apiVersion: v1
kind: Secret
metadata:
  name: coder-v2
  annotations:
    kubernetes.io/service-account.name: coder-v2
type: kubernetes.io/service-account-token
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: coder-v2
rules:
  - apiGroups: ["", "apps", "networking.k8s.io"]
    resources: ["persistentvolumeclaims", "pods", "deployments", "services", "secrets", "pods/exec","pods/log", "events", "networkpolicies", "serviceaccounts"]
    verbs: ["create", "get", "list", "watch", "update", "patch", "delete", "deletecollection"]
  - apiGroups: ["metrics.k8s.io", "storage.k8s.io"]
    resources: ["pods", "storageclasses"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: coder-v2
subjects:
  - kind: ServiceAccount
    name: coder-v2
roleRef:
  kind: Role
  name: coder-v2
  apiGroup: rbac.authorization.k8s.io
EOF
```

The output should be similar to:

```txt
serviceaccount/coder-v2 created
secret/coder-v2 created
role.rbac.authorization.k8s.io/coder-v2 created
rolebinding.rbac.authorization.k8s.io/coder-v2 created
```

### 2. Modify the Kubernetes template

You can start from our
[example template](../../../examples/templates/kubernetes).

```tf
variable "host" {
  description = "Cluster host address"
  sensitive   = true
}

variable "cluster_ca_certificate" {
  description = "Cluster CA certificate (base64 encoded)"
  sensitive   = true
}

variable "token" {
  description = "Cluster CA token (base64 encoded)"
  sensitive   = true
}

variable "namespace" {
  description = "Namespace"
}

provider "kubernetes" {
  host                   = var.host
  cluster_ca_certificate = base64decode(var.cluster_ca_certificate)
  token                  = base64decode(var.token)
}
```

### Create Coder template with managed variables

Fetch the values from the secret and pass them to Coder. This should work on
macOS and Linux.

To get the cluster address:

```sh
kubectl cluster-info
Kubernetes control plane is running at https://example.domain:6443

export CLUSTER_ADDRESS=https://example.domain:6443
```

To fetch the CA certificate and token:

```sh
export CLUSTER_CA_CERTIFICATE=$(kubectl get secrets coder-v2 -n coder-workspaces -o jsonpath="{.data.ca\.crt}")

export CLUSTER_SERVICEACCOUNT_TOKEN=$(kubectl get secrets coder-v2 -n coder-workspaces -o jsonpath="{.data.token}")
```

Create the template with these values:

```sh
coder templates push \
    --variable host=$CLUSTER_ADDRESS \
    --variable cluster_ca_certificate=$CLUSTER_CA_CERTIFICATE \
    --variable token=$CLUSTER_SERVICEACCOUNT_TOKEN \
    --variable namespace=coder-workspaces
```

If you're on a Windows machine (or if one of the commands fail), try grabbing
the values manually:

```sh
# Get cluster API address
kubectl cluster-info

# Get cluster CA and token (base64 encoded)
kubectl get secrets coder-service-account-token -n coder-workspaces -o jsonpath="{.data}"

coder templates push \
    --variable host=API_ADDRESS \
    --variable cluster_ca_certificate=CLUSTER_CA_CERTIFICATE \
    --variable token=CLUSTER_SERVICEACCOUNT_TOKEN \
    --variable namespace=coder-workspaces
```

---

# JFrog Artifactory integration

Source: https://coder.com/docs/admin/integrations/jfrog-artifactory

Use Coder and JFrog Artifactory together to secure your development environments
without disturbing your developers' existing workflows.

This guide will demonstrate how to use JFrog Artifactory as a package registry
within a workspace.

## Requirements

- A JFrog Artifactory instance
- 1:1 mapping of users in Coder to users in Artifactory by email address or
  username
- Repositories configured in Artifactory for each package manager you want to
  use

## Provisioner Authentication

The most straight-forward way to authenticate your template with Artifactory is
by using our official Coder [modules](https://registry.coder.com). We publish
two type of modules that automate the JFrog Artifactory and Coder integration.

1. [JFrog-OAuth](https://registry.coder.com/modules/jfrog-oauth)
1. [JFrog-Token](https://registry.coder.com/modules/jfrog-token)

### JFrog-OAuth

This module works with both JFrog SaaS (for example, `example.jfrog.io`) and self-hosted (on-premises) Artifactory.
It uses Coder's [external-auth](../external-auth/index.md) feature, so each user authenticates with Artifactory through an OAuth flow, and Coder issues a user-scoped access token to each workspace.

To set this up, follow these steps:

1. Create an application integration in Artifactory.
   Use `https://<CODER_URL>/external-auth/jfrog/callback` (your Coder deployment URL) as the callback URL and `applied-permissions/user` as the scope.

   **JFrog SaaS** (`example.jfrog.io`): Create the integration from the JFrog Platform UI as an administrator:

   1. Go to **Administration** > **General Management** > **Manage Integrations**, or open `https://<JFROG_URL>/ui/admin/configuration/integrations/application` directly.
   1. Select **New Integration**.
   1. Select **External Applications**.
   1. On the **Create New Application Integration** form, set **Application Name** to `Coder`, set **Application Type** to **Custom Integration**, and enter the callback URL.
   1. Select **Generate Client ID & Secret**.

   **Self-hosted (on-premises)**: First register an integration template in your Helm chart `values.yaml`, then create the application integration in the UI, and select that template as the **Application Type**.
   Replace `CODER_URL` with your Coder deployment URL:

   ```yaml
   artifactory:
     enabled: true
     frontend:
     extraEnvironmentVariables:
       - name: JF_FRONTEND_FEATURETOGGLER_ACCESSINTEGRATION
         value: "true"
     access:
     accessConfig:
       integrations-enabled: true
       integration-templates:
         - id: "1"
           name: "CODER"
           redirect-uri: "https://CODER_URL/external-auth/jfrog/callback"
           scope: "applied-permissions/user"
   ```

1. Add a new [external authentication](../external-auth/index.md) to Coder by setting these environment variables in a manner consistent with your Coder deployment.
   Replace `JFROG_URL` with your JFrog Artifactory base URL, and the client ID and secret with the values from step 1:

   ```dotenv
   # JFrog Artifactory External Auth
   CODER_EXTERNAL_AUTH_1_ID="jfrog"
   CODER_EXTERNAL_AUTH_1_TYPE="jfrog"
   CODER_EXTERNAL_AUTH_1_CLIENT_ID="YYYYYYYYYYYYYYY"
   CODER_EXTERNAL_AUTH_1_CLIENT_SECRET="XXXXXXXXXXXXXXXXXXX"
   CODER_EXTERNAL_AUTH_1_DISPLAY_NAME="JFrog Artifactory"
   CODER_EXTERNAL_AUTH_1_DISPLAY_ICON="/icon/jfrog.svg"
   CODER_EXTERNAL_AUTH_1_AUTH_URL="https://JFROG_URL/ui/authorization"
   CODER_EXTERNAL_AUTH_1_SCOPES="applied-permissions/user"
   ```

1. Create or edit a Coder template and use the [JFrog-OAuth](https://registry.coder.com/modules/jfrog-oauth) module to configure the integration:

   ```tf
   module "jfrog" {
     count          = data.coder_workspace.me.start_count
     source         = "registry.coder.com/coder/jfrog-oauth/coder"
     version        = "~> 1.0"
     agent_id       = coder_agent.example.id
     jfrog_url      = "https://example.jfrog.io"
     username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"

     package_managers = {
       npm    = ["npm", "@scoped:npm-scoped"]
       go     = ["go", "another-go-repo"]
       pypi   = ["pypi", "extra-index-pypi"]
       docker = ["example-docker-staging.jfrog.io", "example-docker-production.jfrog.io"]
     }
   }
   ```

### JFrog-Token

This module makes use of the [Artifactory terraform
provider](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs) and an admin-scoped token to create
user-scoped tokens for each user by matching their Coder email or username with
Artifactory. This can be used for both SaaS and self-hosted (on-premises)
Artifactory instances.

To set this up, follow these steps:

1. Get a JFrog access token from your Artifactory instance. The token must be an [admin token](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs#access-token) with scope `applied-permissions/admin`.

1. Create or edit a Coder template and use the [JFrog-Token](https://registry.coder.com/modules/jfrog-token) module to configure the integration and pass the admin token. It is recommended to store the token in a sensitive Terraform variable to prevent it from being displayed in plain text in the terraform state:

   ```tf
   variable "artifactory_access_token" {
     type      = string
     sensitive = true
   }

   module "jfrog" {
     source                   = "registry.coder.com/coder/jfrog-token/coder"
     version                  = "~> 1.0"
     agent_id                 = coder_agent.example.id
     jfrog_url                = "https://XXXX.jfrog.io"
     artifactory_access_token = var.artifactory_access_token
     package_managers = {
       npm    = ["npm", "@scoped:npm-scoped"]
       go     = ["go", "another-go-repo"]
       pypi   = ["pypi", "extra-index-pypi"]
       docker = ["example-docker-staging.jfrog.io", "example-docker-production.jfrog.io"]
     }
   }
   ```

> [!NOTE]
> The admin-level access token is used to provision user tokens and is never exposed to developers or stored in workspaces.

If you don't want to use the official modules, you can read through the [example template](../../../examples/jfrog/docker), which uses Docker as the underlying compute. The
same concepts apply to all compute types.

## Air-Gapped Deployments

See the [air-gapped deployments](../templates/extending-templates/modules.md#offline-installations) section for instructions on how to use Coder modules in an offline environment with Artifactory.

## Next Steps

- See the [full example Docker template](../../../examples/jfrog/docker).

- To serve extensions from your own VS Code Marketplace, check out
  [code-marketplace](https://github.com/coder/code-marketplace#artifactory-storage).

---

# Island browser integration

Source: https://coder.com/docs/admin/integrations/island

<div>
  <a href="https://github.com/ericpaulsen" style="text-decoration: none; color: inherit;">
    <span style="vertical-align:middle;">Eric Paulsen</span>
  </a>
</div>
April 24, 2024

---

[Island](https://www.island.io/) is an enterprise-grade browser, offering a Chromium-based experience
similar to popular web browsers like Chrome and Edge. It includes built-in
security features for corporate applications and data, aiming to bridge the gap
between consumer-focused browsers and the security needs of the enterprise.

Coder natively integrates with Island's feature set, which include data
loss protection (DLP), application awareness, browser session recording, and
single sign-on (SSO). This guide intends to document these feature categories
and how they apply to your Coder deployment.

## General Configuration

### Create an Application Group for Coder

We recommend creating an Application Group specific to Coder in the Island
Management console. This Application Group object will be referenced when
creating browser policies.

[See the Island documentation for creating an Application Group](https://documentation.island.io/docs/create-and-configure-an-application-group-object).

## Advanced Data Loss Protection

Integrate Island's advanced data loss prevention (DLP) capabilities with
Coder's cloud development environment (CDE), enabling you to control the
"last mile" between developers' CDE and their local devices,
ensuring that sensitive IP remains in your centralized environment.

### Block cut, copy, paste, printing, screen share

1. [Create a Data Sandbox Profile](https://documentation.island.io/docs/create-and-configure-a-data-sandbox-profile).

1. Configure the following actions to allow/block (based on your security
   requirements).

   - Screenshot and Screen Share
   - Printing
   - Save Page
   - Clipboard Limitations

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the Data Sandbox Profile.

1. Define the Coder Application group as the Destination Object.

1. Define the Data Sandbox Profile as the Action in the Last Mile Protection
   section.

### Conditionally allow copy on Coder's CLI authentication page

1. [Create a URL Object](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) with the following configuration.

   - **Include**
   - **URL type**: Wildcard
   - **URL address**: `coder.example.com/cli-auth`
   - **Casing**: Insensitive

1. [Create a Data Sandbox Profile](https://documentation.island.io/docs/create-and-configure-a-data-sandbox-profile).

1. Configure action to allow copy/paste.

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the Data Sandbox Profile.

1. Define the URL Object you created as the Destination Object.

1. Define the Data Sandbox Profile as the Action in the Last Mile Protection
   section.

### Prevent file upload/download from the browser

1. Create a Protection Profiles for both upload/download.

   - [Upload documentation](https://documentation.island.io/docs/create-and-configure-an-upload-protection-profile)
   - [Download documentation](https://documentation.island.io/v1/docs/en/create-and-configure-a-download-protection-profile)

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the Protection Profiles.

1. Define the Coder Application group as the Destination Object.

1. Define the applicable Protection Profile as the Action in the Data Protection
   section.

### Scan files for sensitive data

1. [Create a Data Loss Prevention scanner](https://documentation.island.io/docs/create-a-data-loss-prevention-scanner).

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the DLP Scanner.

1. Define the Coder Application group as the Destination Object.

1. Define the DLP Scanner as the Action in the Data Protection section.

## Application Awareness and Boundaries

Ensure that Coder is only accessed through the Island browser, guaranteeing that
your browser-level DLP policies are always enforced, and developers can't
sidestep such policies simply by using another browser.

### Configure browser enforcement, conditional access policies

Create a conditional access policy for your configured identity provider.

Note that the configured IdP must be the same for both Coder and Island.

- [Azure Active Directory/Entra ID](https://documentation.island.io/docs/configure-browser-enforcement-for-island-with-azure-ad#create-and-apply-a-conditional-access-policy)
- [Okta](https://documentation.island.io/docs/configure-browser-enforcement-for-island-with-okta)
- [Google](https://documentation.island.io/docs/configure-browser-enforcement-for-island-with-google-enterprise)

## Browser Activity Logging

Govern and audit in-browser terminal and IDE sessions using Island, such as
screenshots, mouse clicks, and keystrokes.

### Activity Logging Module

1. [Create an Activity Logging Profile](https://documentation.island.io/docs/create-and-configure-an-activity-logging-profile). Supported browser
   events include:

   - Web Navigation
   - File Download
   - File Upload
   - Clipboard/Drag & Drop
   - Print
   - Save As
   - Screenshots
   - Mouse Clicks
   - Keystrokes

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the Activity Logging Profile.

1. Define the Coder Application group as the Destination Object.

1. Define the Activity Logging Profile as the Action in the Security &
   Visibility section.

## Identity-aware logins (SSO)

Integrate Island's identity management system with Coder's
authentication mechanisms to enable identity-aware logins.

### Configure single sign-on (SSO) seamless authentication between Coder and Island

Configure the same identity provider (IdP) for both your Island and Coder
deployment. Upon initial login to the Island browser, the user's session
token will automatically be passed to Coder and authenticate their Coder
session.

---

# DX PlatformX

Source: https://coder.com/docs/admin/integrations/platformx

[DX](https://getdx.com) is a developer intelligence platform used by engineering
leaders and platform engineers. Coder notifications can be transformed to
[PlatformX](https://getdx.com/platformx) events, allowing platform engineers to
measure activity and send pulse surveys to subsets of Coder users to understand
their experience.

![PlatformX Events in Coder](../../images/integrations/platformx-screenshot.png)

## Requirements

You'll need:

- Coder v2.19+
- A PlatformX subscription from [DX](https://getdx.com/)
- A platform to host the integration, such as:
  - AWS Lambda
  - Google Cloud Run
  - Heroku
  - Kubernetes
  - Or any other platform that can run Python web applications

## coder-platformx-events-middleware

Coder sends [notifications](../monitoring/notifications/index.md) via webhooks
to coder-platformx-events-middleware, which processes and reformats the payload
into a structure compatible with [PlatformX by DX](https://help.getdx.com/en/articles/7880779-getting-started).

For more information about coder-platformx-events-middleware and how to
integrate it with your Coder deployment and PlatformX events, refer to the
[coder-platformx-notifications](https://github.com/coder/coder-platformx-notifications)
repository.

### Supported Notification Types

coder-platformx-events-middleware supports the following [Coder notifications](../monitoring/notifications/index.md):

- Workspace Created
- Workspace Manually Updated
- User Account Created
- User Account Suspended
- User Account Activated

### Environment Variables

The application expects the following environment variables when started.
For local development, create a `.env` file in the project root with the following variables.
A `.env.sample` file is included:

| Variable         | Description                                | Example                                      |
|------------------|--------------------------------------------|----------------------------------------------|
| `LOG_LEVEL`      | Logging level (`DEBUG`, `INFO`, `WARNING`) | `INFO`                                       |
| `GETDX_API_KEY`  | API key for PlatformX                      | `your-api-key`                               |
| `EVENTS_TRACKED` | Comma-separated list of tracked events     | `"Workspace Created,User Account Suspended"` |

### Logging

Logs are printed to the console and can be adjusted using the `LOG_LEVEL` variable. The available levels are:

| Level     | Description                           |
|-----------|---------------------------------------|
| `DEBUG`   | Most verbose, useful for debugging    |
| `INFO`    | Standard logging for normal operation |
| `WARNING` | Logs only warnings and errors         |

### API Endpoints

- `GET /` - Health check endpoint
- `POST /` - Webhook receiver

---

# DX

Source: https://coder.com/docs/admin/integrations/dx-data-cloud

[DX](https://getdx.com) is a developer intelligence platform used by engineering
leaders and platform engineers.

DX uses metadata attributes to assign information to individual users.
While it's common to segment users by `role`, `level`, or `geo`, it’s become increasingly
common to use DX attributes to better understand usage and adoption of tools.

You can create a `Coder` attribute in DX to segment and analyze the impact of Coder usage on a developer’s work, including:

- Understanding the needs of power users or low Coder usage across the org
- Correlate Coder usage with qualitative and quantitative engineering metrics,
  such as PR throughput, deployment frequency, deep work, dev environment toil, and more.
- Personalize user experiences

## Requirements

- A DX subscription
- Access to Coder user data through the Coder CLI, Coder API, an IdP, or an existing Coder-DX integration
- Coordination with your DX Customer Success Manager

## Extract Your Coder User List

<div class="tabs">

You can use the Coder CLI, Coder API, or your Identity Provider (IdP) to extract your list of users.

If your organization already uses the Coder-DX integration, you can find a list of active Coder users directly within DX.

### CLI

Use `users list` with `jq` to export the list of users to a CSV file:

```sh
coder users list --output json | \
  jq -r '["username","email","created_at","status"], (.[] | [.username, .email, .created_at, .status]) | @csv' > users.csv
```

Visit the [users list](../../reference/cli/users/list.md) documentation for more options.

### API

Use [get users](../../reference/api/users.md#get-users):

```sh
curl -X GET http://coder-server:8080/api/v2/users \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

To export the results to a CSV file, you can use the `jq` tool to process the JSON response:

```sh
curl -X GET http://coder-server:8080/api/v2/users \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY' | \
  jq -r '.users | (map(keys) | add | unique) as $cols | $cols, (.[] | [.[$cols[]]] | @csv)' > users.csv
```

Visit the [get users](../../reference/api/users.md#get-users) documentation for more options.

### IdP

If your organization uses a centralized IdP to manage user accounts, you can extract user data directly from your IdP.

This is particularly useful if you need additional user attributes managed within your IdP.

</div>

## Contact your DX Customer Success Manager

Provide the file to your dedicated DX Customer Success Manager (CSM).

Your CSM will import the CSV of individuals using Coder, as well as usage frequency (if applicable) into DX to create a `Coder` attribute.

After the attribute is uploaded, you'll have a Coder filter option within your DX reports allowing you to:

- Perform cohort analysis (Coder user vs non-user)
- Understand unique behaviors and patterns across your Coder users
- Run a [study](https://getdx.com/studies/) or setup a [PlatformX](https://getdx.com/platformx/) event for deeper analysis

## Related Resources

- [DX Data Cloud Documentation](https://docs.getdx.com/)
- [Coder CLI](../../reference/cli/users/index.md)
- [Coder API](../../reference/api/users.md)
- [PlatformX Integration](./platformx.md)

---

# Integrate HashiCorp Vault with Coder

Source: https://coder.com/docs/admin/integrations/vault

<div>
  <a href="https://github.com/matifali" style="text-decoration: none; color: inherit;">
    <span style="vertical-align:middle;">Muhammad Atif Ali</span>
  </a>
</div>
August 05, 2024

---

This guide describes the process of integrating [HashiCorp Vault](https://www.vaultproject.io/) into Coder workspaces.

Coder makes it easy to integrate HashiCorp Vault with your workspaces by
providing official Terraform modules to integrate Vault with Coder. This guide
will show you how to use these modules to integrate HashiCorp Vault with Coder.

## The `vault-github` module

The [`vault-github`](https://registry.coder.com/modules/vault-github) module is a Terraform module that allows you to
authenticate with Vault using a GitHub token. This module uses the existing
GitHub [external authentication](../external-auth/index.md) to get the token and authenticate with Vault.

To use this module, add the following code to your Terraform configuration.

```tf
module "vault" {
  source               = "registry.coder.com/modules/vault-github/coder"
  version              = "1.0.7"
  agent_id             = coder_agent.example.id
  vault_addr           = "https://vault.example.com"
  coder_github_auth_id = "my-github-auth-id"
}
```

This module installs and authenticates the `vault` CLI in your Coder workspace.

Users then can use the `vault` CLI to interact with Vault; for example, to fetch
a secret stored in the KV backend.

```sh
vault kv get -namespace=YOUR_NAMESPACE -mount=MOUNT_NAME SECRET_NAME
```

---

# OAuth2 provider

Source: https://coder.com/docs/admin/integrations/oauth2-provider

> [!NOTE]
> The OAuth2 provider is off by default.
> Set `CODER_OAUTH2_PROVIDER_ENABLE=true` to turn it on.
> The `oauth2` experiment has been removed, and setting `CODER_EXPERIMENTS=oauth2` now only logs a warning and does nothing.
> Switch to `CODER_OAUTH2_PROVIDER_ENABLE=true` instead.

Coder can act as an OAuth2 authorization server, allowing third-party applications to authenticate users through Coder and access the Coder API on their behalf.
This enables integrations where external applications can leverage Coder's authentication and user management.

## Requirements

- Admin privileges in Coder
- `CODER_OAUTH2_PROVIDER_ENABLE=true` set on the control plane
- HTTPS recommended for production deployments

## Enable OAuth2 provider

The provider is off by default.
While it is off, the OAuth2 endpoints and discovery documents return 404 and the **OAuth2 Applications** page is hidden.
Turn it on with the CLI flag:

```sh
coder server --oauth2-provider-enable
```

Or set the environment variable:

```dotenv
CODER_OAUTH2_PROVIDER_ENABLE=true
```

Or set it in the YAML configuration file:

```yaml
oauth2:
  provider:
    enable: true
```

For Kubernetes deployments that use the Helm chart, add the environment variable to `coder.env` in your values file:

```yaml
coder:
  env:
    - name: CODER_OAUTH2_PROVIDER_ENABLE
      value: "true"
```

Existing applications, secrets, and user authorizations are kept while the provider is off and work again when you turn it on.
Turning the provider off does not invalidate access tokens it already issued.
Those tokens keep authenticating to the regular Coder API while the OAuth2 refresh and revocation endpoints return 404.
Treat the setting as a way to stop new authorizations rather than as a way to revoke access, and delete the application before you disable the provider if you need to cut off every user's existing tokens too.

## Create OAuth2 applications

<a id="creating-oauth2-applications"></a>

### Create an application in the web UI

<a id="method-1-web-ui"></a>

1. Navigate to **Deployment Settings** > **OAuth2 Applications**.
2. On the **Applications** tab, select **Add application**.
3. Fill in the application details:
   - **Name**: Your application name
   - **Default callback**: `https://yourapp.example.com/callback` (web) or `myapp://callback` (native/desktop). Select **Add redirect URI** for additional callback URLs.
   - **Icon**: Optional icon URL
   - **Allowed scopes**: Optional. Refer to [Scopes](./scopes.md).
4. Select **Create application**.

Coder creates the application and takes you to its details page, which prompts you to generate a client secret.

### Create an application with the API

<a id="method-2-management-api"></a>

Create an application using the Coder API:

```sh
curl -X POST \
  -H "Authorization: Bearer $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Application",
    "redirect_uris": [
      "https://myapp.example.com/callback",
      "http://localhost:8080/callback"
    ],
    "icon": "https://myapp.example.com/icon.png"
  }' \
  "$CODER_URL/api/v2/oauth2-provider/apps"
```

`callback_url` is still accepted and still returned, but it is deprecated: it is equal to the first entry in `redirect_uris`. New scripts should send and read `redirect_uris` instead.

Update an application with `PUT`. Fetch it first and edit the fields you want to change, then send the result back:

```sh
curl -X PUT \
  -H "Authorization: Bearer $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My Application",
    "redirect_uris": ["https://myapp.example.com/callback"],
    "icon": "https://myapp.example.com/icon.png"
  }' \
  "$CODER_URL/api/v2/oauth2-provider/apps/$APP_ID"
```

`name` is required on every `PUT`, and `icon` is cleared if you leave it out.
`redirect_uris` replaces the stored list when present and keeps it when omitted.
`scope` is kept when omitted; refer to [Scopes](./scopes.md) for how to change it.

Add an optional `scope` field to restrict which scopes the application's clients may request.
Refer to [Scopes](./scopes.md) for how the allowlist is applied and how to change it later.

Generate a client secret:

```sh
curl -X POST \
  -H "Authorization: Bearer $CODER_SESSION_TOKEN" \
  "$CODER_URL/api/v2/oauth2-provider/apps/$APP_ID/secrets"
```

The response includes `client_secret_full`, the plaintext secret. Save it now: later reads of this application return only a truncated version.

Every client, whichever method you used to create its application, must complete PKCE (Proof Key for Code Exchange) to exchange a code for a token; refer to [Authorization code flow](./integration-patterns.md#authorization-code-flow) before you start integrating.

## Dynamic Client Registration

Dynamic Client Registration ([RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591)) lets a client register itself against `/oauth2/register` instead of an admin creating the application manually. It's **disabled by default**; an owner must turn it on before any client can self-register.

Change the setting in the web UI:

1. Navigate to **Deployment Settings** > **OAuth2 Applications**.
2. Select the **Settings** tab.
3. Select **Enable** or **Disable** next to **Dynamic Client Registration**.

Enabling asks you to confirm first.
Disabling does not.
The tab is linkable directly at `https://$CODER_ACCESS_URL/deployment/oauth2-provider/apps?tab=settings`.

Viewing the tab requires permission to view deployment configuration, and changing the setting requires permission to edit it.
Without edit permission the button is present but inactive, and the page says why.

Check or change the setting with the CLI:

```sh
coder oauth2-provider dcr enable
coder oauth2-provider dcr disable
```

Or with the management API:

```sh
curl -X PUT \
  -H "Authorization: Bearer $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dynamic_client_registration_enabled": true}' \
  "$CODER_URL/api/v2/oauth2-provider/settings"
```

```sh
curl -H "Authorization: Bearer $CODER_SESSION_TOKEN" \
  "$CODER_URL/api/v2/oauth2-provider/settings"
```

Disabling only blocks *new* self-registrations. Applications that already
registered while it was enabled keep authorizing and exchanging tokens
normally; disabling does not revoke or otherwise affect them.

An application may list several `redirect_uris`, whether it registered itself or an admin created it.
A request may present any of them, and the code it receives can only be exchanged with that same URI.
The first entry is the primary callback: it is what the web UI shows for the application, and what a request that omits `redirect_uri` is sent to.
An admin can edit the list through the management API, and a self-registered client can update its own list with its registration access token.
The admin `PUT` also validates the stored name, so a self-registered client whose name has leading or trailing whitespace can only be updated with its registration access token.

<a id="next-steps"></a>

## Learn more

<a id="integration-patterns"></a>

- [Integration patterns](./integration-patterns.md): client authentication methods, the PKCE flow, and discovery endpoints
  - <a id="client-authentication-methods"></a>[Client authentication methods](./integration-patterns.md#client-authentication-methods)
  - <a id="standard-oauth2-flow"></a><a id="pkce-flow-required"></a>[Authorization code flow](./integration-patterns.md#authorization-code-flow)
  - <a id="discovery-endpoints"></a><a id="standards-compliance"></a>[Discovery endpoints](./integration-patterns.md#discovery-endpoints)

<a id="scopes"></a>

- [Scopes](./scopes.md): how access is bounded

<a id="token-management"></a>

- [Token management](./token-management.md): refresh, revocation, and deletion
  - <a id="refresh-tokens"></a>[Refresh tokens](./token-management.md#refresh-tokens)
  - <a id="revoke-a-token"></a>[Revoke a token](./token-management.md#revoke-a-token)
  - <a id="revoke-access"></a>[Revoke your authorization](./token-management.md#revoke-your-authorization-for-an-application)
  - <a id="delete-an-application"></a>[Delete an application](./token-management.md#delete-an-application)

<a id="callback-url-schemes"></a>

- [Callback URL schemes](./callback-url-schemes.md): accepted redirect URIs

<a id="common-issues"></a><a id="oauth2-endpoints-return-404"></a><a id="invalid-redirect_uri"></a><a id="invalid-callback-url-on-the-consent-page"></a><a id="invalid_scope-returned-to-your-callback"></a><a id="invalid_grant-for-a-scope-the-deployment-cannot-mint"></a><a id="invalid_scope-for-a-refresh-that-names-a-scope"></a><a id="invalid_client-for-a-refresh-or-a-revocation"></a><a id="invalid_request-for-client_secret-in-the-query-string"></a><a id="unsupported_response_type-returned-to-your-callback"></a><a id="invalid_request-for-code_challenge_method"></a><a id="invalid_request-for-a-rejected-parameter"></a><a id="invalid_request-from-post-oauth2tokens-for-a-repeated-parameter"></a><a id="invalid_target-for-a-rejected-resource"></a><a id="pkce-verification-failed"></a><a id="public-clients-may-not-use-the-mailtotelsms-scheme"></a>

- [Troubleshooting](./troubleshooting.md): look up an error by its exact code or message

- [Security and limitations](./security.md): security considerations and current limitations
  - <a id="security-considerations"></a>[Security considerations](./security.md#security-considerations)
  - <a id="limitations"></a>[Limitations](./security.md#limitations)

- Check [External Authentication](../../external-auth/index.md) for configuring Coder as an OAuth2 client
- Review the [API Reference](../../../reference/api/index.md) for complete endpoint documentation

## Feedback

Report issues and feedback through [GitHub Issues](https://github.com/coder/coder/issues) with the `oauth2` label.

---

# OAuth2 provider integration patterns

Source: https://coder.com/docs/admin/integrations/oauth2-provider/integration-patterns

This page covers how a client proves who it is and completes a login: the supported ways to prove identity, the standard login steps, the required PKCE (Proof Key for Code Exchange) step, and how a client finds the right web addresses to use.

- [OAuth2 provider](./index.md): turn on the provider and create an application
- [Scopes](./scopes.md): control what a client is allowed to access
- [Token management](./token-management.md): refresh, cancel, or delete access
- [Callback URL schemes](./callback-url-schemes.md): which redirect addresses are allowed

## Client authentication methods

Coder supports the following OAuth2 client authentication methods at the token endpoint (`/oauth2/tokens`):

- `client_secret_basic` (recommended): HTTP Basic authentication (RFC 6749 §2.3.1). The username is `client_id` and the password is `client_secret`.
- `client_secret_post`: Form-based authentication where `client_id` and `client_secret` are sent in the request body.
- `none`: No client secret.
  The client is a public client and authenticates with PKCE alone (RFC 7591 §2, OAuth 2.1 §2.1).
  Available only through [Dynamic Client Registration](./index.md#dynamic-client-registration), which is disabled by default, since a client's type is set when it registers and apps created through the admin UI or API are always confidential.

Coder supports both methods, so existing integrations using `client_secret_post` don't need to switch to `client_secret_basic`.

Send `client_secret` in the request body or in the `Authorization` header.
`POST /oauth2/tokens` and `POST /oauth2/revoke` reject a `client_secret` value in the URL query string with `invalid_request`, because OAuth 2.1 section 2.4.1 does not allow it there.
Refer to ["invalid_request" for `client_secret` in the query string](./troubleshooting.md#invalid_request-for-client_secret-in-the-query-string) for the exceptions and the log line to search for.

Public clients suit native, mobile, and CLI applications that cannot keep a secret confidential. Note the redirect URI restrictions below before choosing one.

Opening a public client on the **OAuth2 Applications** page shows no client secrets section, since a public client has no secret to display or generate.

If you use Dynamic Client Registration (RFC 7591) and omit `token_endpoint_auth_method`, clients default to `client_secret_basic`. To request `client_secret_post`, set `token_endpoint_auth_method` to `client_secret_post` in the registration request. To register a public client, set it to `none`: Coder issues no `client_secret`, and the registration response omits that field entirely.

> [!IMPORTANT]
> Which redirect URI schemes and hosts a client may register, including the loopback host and port rules for public and confidential clients, is a separate restriction from client authentication.
> Refer to [Callback URL schemes](./callback-url-schemes.md).

A client's type is fixed when it registers.
An RFC 7592 update that would move a client between public and confidential is rejected with `invalid_client_metadata`, since the client either holds a secret that would stop being required or has none and no way to be issued one.
Switching between `client_secret_basic` and `client_secret_post` is allowed, because both are confidential.
To change type, register a new client.

Clients registered with `token_endpoint_auth_method: none` before Coder honored it are stored as confidential and still require their `client_secret`.
Coder reports `client_secret_basic` for those clients so that what it reports matches what it enforces, and the mismatch clears the next time the client updates its registration using the value Coder reported.

If client authentication fails, the token endpoint returns **HTTP 401** with an OAuth2 `invalid_client` error and a `WWW-Authenticate: Basic realm="coder"` response header.

## Authorization code flow

Every authorization code flow requires PKCE (Proof Key for Code Exchange).
Coder enforces PKCE in compliance with the OAuth 2.1 specification, for both public and confidential clients.

> [!NOTE]
> `code_verifier` and `code_challenge` must each be 43-128 characters from the unreserved character set `[A-Za-z0-9-._~]` (RFC 7636 §4.1).
> A value outside these bounds is rejected with an `invalid_request` error, at the token endpoint for `code_verifier` and at the authorization endpoint for `code_challenge`.

1. Generate a code verifier and challenge:

   ```sh
   CODE_VERIFIER=$(openssl rand -base64 96 | tr -d '\n' | tr '+/' '-_' | tr -d '=')
   CODE_CHALLENGE=$(echo -n $CODE_VERIFIER | openssl dgst -sha256 -binary | base64 | tr -d "=" | tr '+/' '-_')
   ```

2. Redirect users to Coder's authorization endpoint:

   ```txt
   https://coder.example.com/oauth2/authorize?
     client_id=your-client-id&
     response_type=code&
     code_challenge=$CODE_CHALLENGE&
     code_challenge_method=S256&
     redirect_uri=https://yourapp.example.com/callback&
     state=random-string
   ```

3. Exchange the authorization code for an access token, using the code verifier (refer to [Client authentication methods](#client-authentication-methods) for how to authenticate):

   **Confidential client**

   ```sh
   curl -X POST \
     -u "$CLIENT_ID:$CLIENT_SECRET" \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "grant_type=authorization_code" \
     -d "code=$AUTH_CODE" \
     -d "code_verifier=$CODE_VERIFIER" \
     -d "redirect_uri=https://yourapp.example.com/callback" \
     "$CODER_URL/oauth2/tokens"
   ```

   **Public client (`token_endpoint_auth_method: none`)**

   Send `client_id` in the form body and omit `client_secret` entirely.
   The code verifier is the only proof of possession, and must satisfy RFC 7636 §4.1 (43-128 characters from `[A-Za-z0-9-._~]`).

   ```sh
   curl -X POST \
     -H "Content-Type: application/x-www-form-urlencoded" \
     -d "grant_type=authorization_code" \
     -d "code=$AUTH_CODE" \
     -d "client_id=$CLIENT_ID" \
     -d "code_verifier=$CODE_VERIFIER" \
     -d "redirect_uri=https://yourapp.example.com/callback" \
     "$CODER_URL/oauth2/tokens"
   ```

4. Use the access token to call Coder's API:

   ```sh
   curl -H "Authorization: Bearer $ACCESS_TOKEN" \
     "$CODER_URL/api/v2/users/me"
   ```

   Send the access token in the `Authorization` header.
   Coder ignores an OAuth2 access token in the URL query string, as OAuth 2.1 section 5.1 requires.
   This endpoint requires a signed-in user, so it answers HTTP 401.
   Refer to [HTTP 401 for an access token in the query string](./troubleshooting.md#http-401-for-an-access-token-in-the-query-string) for endpoints that behave differently.

## Discovery endpoints

Coder provides OAuth2 discovery endpoints for programmatic integration:

- **Authorization Server Metadata**: `GET /.well-known/oauth-authorization-server`
- **Protected Resource Metadata**: `GET /.well-known/oauth-protected-resource`

These endpoints return server capabilities and endpoint URLs according to [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414) and [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728).

`token_endpoint_auth_methods_supported` lists every method the token endpoint accepts, including `none`.
It is not gated on [Dynamic Client Registration](./index.md#dynamic-client-registration), since existing public clients still exchange tokens when new registrations are disabled.
`registration_endpoint` is advertised only while Dynamic Client Registration is enabled, so that field, not this one, tells a client whether it can register a new public client.

## Standards compliance

This implementation follows established OAuth2 standards including [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749) (OAuth2 core), [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636) (PKCE), and the [OAuth 2.1 draft](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-16).
Coder enforces OAuth 2.1 requirements including mandatory PKCE for all authorization code grants, exact redirect URI string matching with the [RFC 8252](https://datatracker.ietf.org/doc/html/rfc8252) loopback port exception, rejection of the implicit grant, and CSRF protections on consent pages.

## Learn more

- Review [Scopes](./scopes.md) for how access is bounded
- Review [Token management](./token-management.md) for refresh, revocation, and deletion
- Check [Troubleshooting](./troubleshooting.md) if a request fails

---

# OAuth2 provider scopes

Source: https://coder.com/docs/admin/integrations/oauth2-provider/scopes

An access token is bounded by the scope negotiated when the user authorized it, on top of that user's own permissions. A token can never do more than its user can.

Scope names come from the same vocabulary as [API key scopes](../../users/sessions-tokens.md#api-key-scopes): individual `resource:action` names such as `workspace:ssh`, and `coder:` composites such as `coder:workspaces.access` that stand for a set of them.
`coder:all` records an unrestricted grant.

A client asks for a scope with the `scope` parameter on the authorization request, space separated:

```txt
https://coder.example.com/oauth2/authorize?
  client_id=your-client-id&
  response_type=code&
  scope=coder:workspaces.access&
  code_challenge=$CODE_CHALLENGE&
  code_challenge_method=S256&
  redirect_uri=https://yourapp.example.com/callback
```

An application can carry a `scope` allowlist.
The client may then request anything that allowlist covers, and is granted the whole allowlist if it requests nothing.
An application with no allowlist honors any requested scope, and a request that names no scope is granted `coder:all`.

An application registered through [Dynamic Client Registration](./index.md#dynamic-client-registration) declares its allowlist in the `scope` field of its registration.
An administrator sets one with the **Allowed scopes** field in the web UI, or with the optional, space-separated `scope` field when [creating an application](../../../reference/api/enterprise.md#create-oauth2-application) through the management API.
When [updating an application](../../../reference/api/enterprise.md#update-oauth2-application), omit `scope` to keep the current allowlist, send a new value to replace it, or send an empty string to clear it and make the application unrestricted.
Dynamic Client Registration keeps only the names this deployment offers, both on `POST /oauth2/register` and on `PUT /oauth2/clients/{client_id}`, and returns the stored list in the response.
A non-empty `scope` that keeps no offered name is rejected with `400 invalid_client_metadata` and the request is not stored.
An update that resends the stored `scope` unchanged keeps it as stored.
An allowlist set through the web UI or the management API is stored as given; a name it holds that this deployment does not offer fails at authorization, as described under ["invalid_scope" returned to your callback](./troubleshooting.md#invalid_scope-returned-to-your-callback).

Use caution when narrowing the scope allowlist of a self-registered application.
Many clients request every scope Coder advertises in `scopes_supported` rather than selecting specific scopes; MCP clients that rely on discovery commonly work this way.
The allowlist is stored on the application and does not affect that advertised list, so the client continues requesting the full set.
Coder rejects requests that exceed the allowlist rather than trimming their scopes, so every new authorization attempt fails with `invalid_scope`.
Previously issued tokens retain their scopes.
Such a client cannot be restricted through its allowlist: narrowing it breaks the client, and clearing it leaves the application unrestricted.
Only a client that can be configured to request fewer scopes can be narrowed, and whoever operates that client makes the change.
An allowlist set by an administrator also does not hold against the client: the holder of the application's `registration_access_token` can replace or clear it at any time with `PUT /oauth2/clients/{client_id}`.
The web UI warns before saving a narrower allowlist, and the application page indicates whether the application was self-registered or created by an administrator.

The consent page states the scope being granted before the user approves it.
A refresh keeps the scope originally granted; a refresh that names a narrower `scope` applies it to the access token it mints, leaving the grant itself unchanged.

## Learn more

- Refer to ["invalid_scope" for a refresh that names a scope](./troubleshooting.md#invalid_scope-for-a-refresh-that-names-a-scope) for how a refresh can narrow the access token it mints
- Check [Troubleshooting](./troubleshooting.md) for scope-related errors

---

# OAuth2 provider token management

Source: https://coder.com/docs/admin/integrations/oauth2-provider/token-management

This page covers three different readers: a developer refreshing or revoking a token, any Coder user ending their own authorization for an application, and a deployment administrator deleting an application.
It covers how to refresh an access token, revoke a token, revoke your own authorization for an application, and delete an application.

- [Client authentication methods](./integration-patterns.md#client-authentication-methods): how to prove identity when refreshing or revoking a token.
  The other two actions on this page use your own Coder login instead.

## Refresh tokens

Refresh an expired access token.

**Option A: HTTP Basic authentication (`client_secret_basic`)**

```sh
curl -X POST \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=$REFRESH_TOKEN" \
  "$CODER_URL/oauth2/tokens"
```

**Option B: Form parameters (`client_secret_post`)**

```sh
curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=$REFRESH_TOKEN" \
  -d "client_id=$CLIENT_ID" \
  -d "client_secret=$CLIENT_SECRET" \
  "$CODER_URL/oauth2/tokens"
```

**Option C: Public client (`none`)**

```sh
curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=$REFRESH_TOKEN" \
  -d "client_id=$CLIENT_ID" \
  "$CODER_URL/oauth2/tokens"
```

## Revoke a token

Revoke one refresh token or access token through the [RFC 7009](https://datatracker.ietf.org/doc/html/rfc7009) endpoint that `revocation_endpoint` advertises.
A confidential client authenticates as it does on a refresh, with HTTP Basic as below or with `client_id` and `client_secret` form fields as in the refresh examples above.
An omitted or wrong secret answers HTTP 401 with `error=invalid_client`:

```sh
curl -X POST \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=$REFRESH_TOKEN" \
  "$CODER_URL/oauth2/revoke"
```

A public client sends `client_id` alone.
Revoking a refresh token also ends the access token issued with it.
A successful revocation returns HTTP 200, but that response does not confirm that the token existed or belonged to your client.
A confidential client that fails to authenticate receives HTTP 401 with `error=invalid_client` and nothing is revoked.

## Revoke your authorization for an application

Revoke your own authorization codes and tokens for an application, using the session token that authorized them:

```sh
curl -X DELETE \
  -H "Authorization: Bearer $CODER_SESSION_TOKEN" \
  "$CODER_URL/oauth2/tokens?client_id=$CLIENT_ID"
```

This ends your own sessions with the application but leaves the application registered, so it can authorize again, and does not affect any other user's tokens for it.
For a cutoff that affects every user, delete the application or one of its client secrets, as described under [Delete an application](#delete-an-application).

## Delete an application

Deleting an application is a separate operation from revoking a single user's tokens.
It removes the registration itself, so the client cannot authorize again without being registered anew, and it revokes every token issued under it, for every user.
Deleting one of an application's client secrets has the same effect on every token issued under that secret.

In the web UI, navigate to **Deployment Settings** > **OAuth2 Applications**, select the application on the **Applications** tab, then select **Delete**.
This requires permission to delete OAuth2 applications.

Or with the management API:

```sh
curl -X DELETE \
  -H "Authorization: Bearer $CODER_SESSION_TOKEN" \
  "$CODER_URL/api/v2/oauth2-provider/apps/$APP_ID"
```

This is also how you remove clients that registered themselves while dynamic client registration was enabled.
Turning the setting off stops new registrations; it does not remove the ones already there.

## Learn more

- Check [Troubleshooting](./troubleshooting.md) if a refresh or revocation fails

---

# OAuth2 provider callback URL schemes

Source: https://coder.com/docs/admin/integrations/oauth2-provider/callback-url-schemes

This page covers which redirect URI schemes and hosts Coder accepts, for both admin-created and self-registered applications.

Custom URI schemes (`myapp://`, `vscode://`, `jetbrains://`, etc.) are fully supported for native and desktop applications.
The OS routes the redirect back to the registered application without requiring a running HTTP server.
A private-use scheme must name a path or an authority, as in `com.example.app:/callback` or `com.example.app://auth/callback`.
The bare form `com.example.app:callback` is rejected.

The out-of-band URN `urn:ietf:wg:oauth:2.0:oob` is accepted from either client type, for clients that display the authorization code for the user to copy rather than receiving it on a redirect. No other URN is accepted.

The following schemes are blocked for security reasons: `javascript:`, `data:`, `file:`, `ftp:`.

Public clients (`token_endpoint_auth_method: none`) additionally cannot register `mailto:`, `tel:`, or `sms:` redirect URIs, since those schemes hand off to another app rather than returning an authorization code to the client. Confidential clients are not subject to this restriction.

A cleartext `http://` redirect URI is accepted only for a local host.
A confidential client may use `localhost`, `127.0.0.1`, `[::1]`, or a `.localhost` subdomain such as `http://app.localhost/callback`.
A public client is limited to `localhost`, `127.0.0.1`, and `[::1]`.
Every other host must use `https://`, so that an authorization code is never delivered in the clear.
The management API and Dynamic Client Registration apply the same rule, so an administrator cannot store a target that a client could not register for itself.

Coder ignores the port of an `http://` redirect URI to `localhost`, `127.0.0.1`, or `[::1]`, for public and confidential clients alike.
RFC 8252 requires this for `127.0.0.1` and `[::1]` so that native apps can choose a port at runtime.
Coder applies it to `localhost` too.
A `.localhost` subdomain still requires an exact port match.
Register `http://127.0.0.1/callback` and present whichever port the client is listening on.

These rules apply to every entry in `redirect_uris`, not only the first one.

## Learn more

- Check [Troubleshooting](./troubleshooting.md) for "Invalid Callback URL" and related errors

---

# OAuth2 provider troubleshooting

Source: https://coder.com/docs/admin/integrations/oauth2-provider/troubleshooting

This page collects the error conditions the OAuth2 provider returns, matched by the exact `error`, `error_description`, or log line you'll see.

- [OAuth2 provider](./index.md): how to turn on and set up the provider
- [Integration patterns](./integration-patterns.md): how a client is supposed to connect and log in

## OAuth2 endpoints return 404

The provider is off.
Set `CODER_OAUTH2_PROVIDER_ENABLE=true` and restart the server.
Refer to [Enable OAuth2 Provider](./index.md#enable-oauth2-provider).

## "Invalid redirect_uri"

Ensure the redirect URI in your request exactly matches one of the redirect URIs registered for your application.
The one exception is the port of a loopback `http://` redirect URI (`localhost`, `127.0.0.1`, `[::1]`), which may differ from the registered one.
Refer to [Callback URL schemes](./callback-url-schemes.md).

## "Invalid Callback URL" on the consent page

If you see this error when authorizing, one of the application's registered redirect URIs is not usable: either it does not parse as a URL, or it uses a blocked scheme (`javascript:`, `data:`, `file:`, or `ftp:`).
The same cause answers `server_error` on `POST /oauth2/authorize`.
Use `GET /api/v2/oauth2-provider/apps/{app}` to see every registered redirect URI, then update the application with a corrected `redirect_uris` list as shown under [Create an application with the API](./index.md#create-an-application-with-the-api).
Refer to [Callback URL schemes](./callback-url-schemes.md) for which values are accepted.

The `coderd` log records the application ID and the stored value.
The response does not, so a bad URL is never echoed back to a browser.

## "invalid_scope" returned to your callback

The authorization endpoint validates the `scope` parameter.
When it cannot grant what was asked for, it redirects to your registered callback with `error=invalid_scope` rather than issuing a code.
The `error_description` opens with the requested name that caused the rejection:

- `unknown or unsupported scope`: this deployment does not offer that name to OAuth2 clients.
  It may not exist, or it may exist and be internal-only, which no version offers.
  Read the current list from `scopes_supported` in `GET /.well-known/oauth-authorization-server`.
- `scope requests permissions beyond this app's allowed scopes`: the name is supported, but the application's `scope` allowlist does not cover it.
  Request less, or widen the allowlist.
  If the application registered itself and an administrator has since narrowed its allowlist, refer to [Scopes](./scopes.md).
- `none of the scopes registered for this app are supported by this deployment`: the application's `scope` allowlist names nothing this deployment offers, so no request against it can succeed, including one that omits `scope`.
  Update the allowlist with supported scopes.
  This description stands alone.
  Dynamic Client Registration drops unsupported names before storing, so this applies to an allowlist set through the web UI or the management API, or to an application that registered before names were checked.
  Such a value was never checked against the catalog, so the response never echoes it; the `coderd` log records the application ID.

Omitting `scope` requests the application's allowlist, or full access if it has none.

The negotiated scope is recorded on the authorization, shown on the consent page, and applied to the access token issued when the code is exchanged.

The token endpoint validates a refresh request's `scope` too, and answers `invalid_scope` in the response body rather than by redirect.
Refer to ["invalid_scope" for a refresh that names a scope](#invalid_scope-for-a-refresh-that-names-a-scope).

## "invalid_grant" for a scope the deployment cannot mint

`POST /oauth2/tokens` mints the access token with the scope recorded on the authorization code, or on the refresh token when refreshing.
If that stored scope names something this deployment cannot mint, the exchange answers HTTP 400 with `error=invalid_grant` and an `error_description` naming the value.

The usual cause is a grant made against a scope the deployment has since dropped.
Authorize again to negotiate a scope it still supports; the stored scope is not something the client can change by requesting a different one.

The exchange also re-checks the code's scope against the application's registered `scope`, which can change during the 10&nbsp;minutes a code stays valid.
Two more descriptions can open the `error_description` here:

- `scope is no longer allowed by this app's registered scopes`: the allowlist narrowed after the code was issued and no longer covers the code's scope.
  Authorize again to negotiate a scope within the new allowlist.
- `none of the scopes registered for this app are supported by this deployment`: the allowlist names nothing this deployment offers, so no code against it can be redeemed.
  Update the allowlist with supported scopes.
  As on the authorize endpoint, the stored value stays out of the response.

A coverage comparison this deployment cannot decide answers HTTP 500 with `error=server_error` and `The requested scope could not be evaluated`; the scope that could not be compared is in the `coderd` logs, not the response.

An application's `scope` allowlist can change through [Dynamic Client Registration](./index.md#dynamic-client-registration), by the application itself, or through the management API, by an administrator.
An application that holds its registration access token can widen its own allowlist again before redeeming a code, so treat this re-check as reflecting the allowlist at redemption time rather than as a constraint on the client.

A refresh is not re-checked against the registration.
That is a Coder policy choice: withdrawing scope from a session already running would break it mid-flight, so a narrowing takes effect at the next authorization.
A refresh token keeps its granted scope until it expires, which can be up to the configured refresh lifetime; revoke the token to cut a live session.

Codes issued before the upgrade that added scope columns carry `coder:all`, recorded as an unrestricted grant.
For an application with a narrower `scope` allowlist, those codes are refused with `scope is no longer allowed by this app's registered scopes` until they expire, which takes at most 10&nbsp;minutes.
Authorizing again issues a code within the current allowlist.

## "invalid_scope" for a refresh that names a scope

`POST /oauth2/tokens` answers HTTP 400 with `error=invalid_scope` when a refresh request names a `scope` the control plane will not grant.
This is the token endpoint, not the authorization endpoint above: there is no redirect, and the error is in the response body.

A refresh may name a `scope` of its own to give up authority.
The narrowing applies to the access token that refresh mints, and to nothing else.
The refresh token continues to represent the scope the user consented to, so the ceiling does not move and a later refresh may ask for a different part of the same grant, or omit `scope` to take the grant whole again.

The request may name any scope the original grant confers **that also appears in `scopes_supported`**, including a single permission out of a composite scope, so a token granted `coder:workspaces.access` can refresh down to `workspace:read` for one call and to `workspace:ssh` for the next.
Two descriptions can open the `error_description`, each opening with the requested name that caused it:

- `scope requests permissions beyond the scope originally granted; a refresh cannot widen a grant, so authorize again to obtain a broader one`: the name is offered, but the resource owner never granted it.
- `unknown or unsupported scope`: this deployment does not offer that name to OAuth2 clients, either because it does not exist or because it is internal.

A refused refresh mints nothing and leaves the refresh token usable, so a client that asked for too much can retry with less rather than re-authorizing.

Only the resource owner lowers the ceiling, by revoking the token or authorizing again with less.
This is also what OAuth 2.1 section 4.3.3 requires: a rotated refresh token carries the scope of the one presented.

Narrowing a composite scope to the low-level names you can request may drop permissions that have no requestable name of their own.
`coder:workspaces.create` confers `organization_member:read`, which a workspace build needs and which `scopes_supported` does not list, so a token narrowed to the fullest set a client can name will fail to create a workspace.
Refresh without a `scope` to return to the composite.

## "invalid_client" for a refresh or a revocation

`POST /oauth2/tokens` with `grant_type=refresh_token` and `POST /oauth2/revoke` answer HTTP 401 with `error=invalid_client` when a confidential client does not authenticate.
The usual causes are a `client_secret` that was omitted, a secret that belongs to a different client, or a secret that has since been deleted or rotated.
Present the client's current secret, as HTTP Basic or as a form parameter, following [Refresh tokens](./token-management.md#refresh-tokens).
The refresh token is not consumed and nothing is revoked by the refusal, so the retry needs no new authorization.
If the secret was deleted, the tokens issued under it were revoked with it, and the client must authorize again.
Public clients have no secret and never receive this error for omitting one.

## "invalid_request" for `client_secret` in the query string

`POST /oauth2/tokens` and `POST /oauth2/revoke` answer HTTP 400 with `error=invalid_request` when `client_secret` appears in the URL query string.
OAuth 2.1 section 2.4.1 allows the secret in the request body or the `Authorization` header only.
Send it as a form parameter or as HTTP Basic, following [Client authentication methods](./integration-patterns.md#client-authentication-methods).

The rule covers `client_secret` only.
Coder still reads `refresh_token`, `code`, and the revocation `token` from the query string.
Send those in the request body too, not in the query string.

A `client_secret` with no value, as in `?client_secret=`, counts as absent under RFC 6749 section 3.2 and is not refused by this rule.
`POST /oauth2/revoke` accepts such a request when the body authenticates.
`POST /oauth2/tokens` answers 400 only when the body also carries a `client_secret`, because it reads the body copy and the empty URL copy as the same parameter sent twice, and the error says so.
An empty query value alone never causes a 400: a request that authenticates with HTTP Basic and sends no secret in the body, or one from a public client, succeeds.

A copy in the body does not excuse one in the URL: the request is refused on the query string alone, whatever the body holds.
The refusal issues no token and revokes nothing, so the retry needs no new authorization.

`GET /oauth2/authorize` is not rejected when its URL carries `client_secret`, because RFC 6749 section 3.1 requires that endpoint to ignore parameters it does not recognize.
Coder ignores the value and logs a warning instead.

Each refusal and the authorization warning write a log line containing `client_secret in the URL query string` with the `app_id`, `remote_addr`, and `user_agent` of the request.
Search the Coder logs for that string to find the integration that sends the secret in the URL.

The log line records that the parameter was present, not that its value was a valid secret.
The check runs before client authentication, so anyone who knows the public `client_id` can produce the same line without credentials.
Confirm with the client's owner that their integration sent the request before rotating.

The check also runs after the `client_id` is resolved.
A request with a missing, malformed, or unknown `client_id` is answered by that lookup first and writes no such line, so an absent line does not mean no integration is leaking.

Rotate the secret that was in the URL.
It is still valid, and a URL is recorded by reverse proxies, load balancers, CDN access logs, shell history, and client libraries.
Coder does not log query strings, so an empty result when you search the Coder logs does not mean the secret stayed private.
Deleting a secret also revokes the tokens issued under it, so the client has to authorize again.

Earlier releases accepted the parameter in the query string.
An integration that relied on that has to move it into the body or the header.

## HTTP 401 for an access token in the query string

Coder ignores an access token issued by the OAuth2 provider when it arrives only in the URL query string, as `?access_token=` or `?coder_session_token=`.
OAuth 2.1 section 5.1 requires the resource server to ignore access tokens in a URI query parameter.
Coder handles the request as if it carried no token at all.
Most endpoints require a signed-in user, so they answer HTTP 401 with a `WWW-Authenticate: Bearer` header.
That header carries no error code, since no token was accepted, and the JSON body says to send the token in the `Authorization` header instead.
A few endpoints also work without a signed-in user, and those handle the request as an anonymous one and return no error.
Send the token in the `Authorization` header instead, as shown under [Authorization code flow](./integration-patterns.md#authorization-code-flow).

The rule applies to tokens the OAuth2 provider issued.
Coder session tokens and API tokens created from the dashboard or the CLI are still accepted in the query string, because browsers cannot set headers on WebSocket connections.
A dashboard page embedded in another application and authenticated with an OAuth2 access token cannot open WebSocket connections, because the page has no other way to send the token on a WebSocket.

A token that also appears in the `Authorization` header, the `Coder-Session-Token` header, or the session cookie is accepted, and the query copy is ignored.

An app served through an external workspace proxy is not covered by this rule.
The proxy forwards the client's request to the primary as a header regardless of how the client sent it to the proxy, so a token sent only in the query string to the proxy can still authenticate, and no warning is logged.

Each ignored token writes a log line containing `oauth2 access token ignored: sent in the URL query string` with the `api_key_id`, `user_id`, `app_id`, `path`, `remote_addr`, and `user_agent` of the request.
The `app_id` matches the application in the **OAuth2 Applications** admin page, and the `user_id` names the user whose authorization the integration is using.
Search the Coder logs for that string to find the integration that sends the token in the URL.
The ignored token stays valid and is not marked as used.

A URL is recorded by reverse proxies, load balancers, CDN access logs, browser history, and `Referer` headers.
Treat a token that was sent this way as exposed and end it in one of these ways:

- The integration owner, who holds the token value and the client credentials, revokes it following [Revoke a token](./token-management.md#revoke-a-token).
- The user named by `user_id` ends their own tokens for the application following [Revoke your authorization for an application](./token-management.md#revoke-your-authorization-for-an-application).
- An administrator deletes the key with the two IDs from the log line, `DELETE /api/v2/users/{user_id}/keys/{api_key_id}`, or cuts off every user of the application by deleting it or one of its secrets following [Delete an application](./token-management.md#delete-an-application).

Earlier releases accepted the token in the query string.
An integration that relied on that has to move it into the `Authorization` header.

## "unsupported_response_type" returned to your callback

Coder supports the authorization code flow only, so `response_type=code` is the single accepted value.
`GET /.well-known/oauth-authorization-server` reports it in `response_types_supported`.

Any other value, including the `token` of the implicit grant, redirects to your registered callback with `error=unsupported_response_type`, an `error_description` of `Only response_type=code is supported`, and the `state` you sent.
This holds for both `GET /oauth2/authorize` and `POST /oauth2/authorize`.

Earlier releases answered on Coder instead: `GET` rendered an "Unsupported Response Type" page and `POST` returned a 400 with a JSON body.
An integration that watched for either now has to read the error from its own callback.

## "invalid_request" for `code_challenge_method`

Coder supports the `S256` challenge method only.
`plain` sends the verifier itself as the challenge, so anything that can observe the authorization request can complete the exchange, which is what PKCE exists to prevent.
Omitting the parameter is allowed and means `S256`.

An unsupported method redirects to your registered callback with `error=invalid_request`, an `error_description` that names the method, and the `state` you sent.
This holds for both `GET /oauth2/authorize` and `POST /oauth2/authorize`.

## "invalid_request" for a rejected parameter

Coder validates every authorization parameter before issuing a code, and reports all the failing fields together in one `error_description`.
Each entry reads `field: reason`, and entries are separated by a semicolon and a space.
Common causes are a `code_challenge` outside the 43 to 128 character unreserved set, and any parameter sent more than once.

The rejection redirects to your registered callback with `error=invalid_request`, an `error_description` naming the fields, and the `state` you sent.
This holds for both `GET /oauth2/authorize` and `POST /oauth2/authorize`.
A description longer than 2048 characters is cut short and marked `(truncated)`.

Parameters the endpoint does not read are ignored, as RFC 6749 Section 3.1 requires, so an OIDC `nonce` or a vendor extension does not fail the request.
A misspelled parameter is ignored on the same rule, so what you see is the failure caused by the parameter you meant to send being absent.

Two failures stay on Coder rather than reaching your callback, because in both cases the callback is not yet trustworthy:

- A `redirect_uri` that does not parse, or that does not exactly match one of the redirect URIs registered for the application.
  Redirecting to it would defeat the check that just rejected it, so Coder answers 400 (refer to ["Invalid redirect_uri"](#invalid-redirect_uri)).
- A `client_id` sent more than once, or one that does not name the application the callback was matched against.
  Coder cannot tell whose registration it is about to redirect to.

Earlier releases answered on Coder for all of these: `GET` rendered an "Invalid Query Parameters" page and `POST` returned a 400 with a JSON body.
An integration that watched for either now has to read the error from its own callback.

## "invalid_request" from `POST /oauth2/tokens` for a repeated parameter

The token endpoint ignores parameters it does not read, as RFC 6749 Section 3.2 requires, so an OIDC `nonce`, a `client_assertion`, or a vendor extension does not fail the exchange.
A misspelled parameter is ignored on the same rule, so what you see is the failure caused by the parameter you meant to send being absent.

A known parameter sent more than once is rejected with a 400 and a JSON body.
The error is `invalid_request`, except for a repeated `grant_type`, which answers `unsupported_grant_type`.

Earlier releases returned 400 `invalid_request` for any parameter the endpoint did not recognize.
An integration that relied on that error to catch a misspelled optional parameter no longer receives it.

## "invalid_target" for a rejected `resource`

`resource` must be an absolute URI without a fragment (RFC 8707).
A value that is not redirects to your registered callback with `error=invalid_target`, an `error_description` naming the field, and the `state` you sent.
`POST /oauth2/token` already answered `invalid_target` for the same value.

If anything else in the request also failed, the answer is `invalid_request` instead, naming every failing field.
Correct them all before retrying: a retry that fixes only `resource` fails again.

## "PKCE verification failed"

Verify that the `code_verifier` used in the token request matches the one used to generate the `code_challenge`.

## "public clients may not use the mailto/tel/sms scheme"

This error appears during client registration when a public client (`token_endpoint_auth_method: none`) registers a redirect URI using the `mailto:`, `tel:`, or `sms:` scheme.
These schemes hand off to a mail client, dialer, or SMS app instead of returning control to the application that started the flow, so a public client registered with one of them could never complete authorization.
Register a redirect URI the client can actually receive control on instead, such as a custom scheme (`myapp://callback`) or a loopback HTTP address.

## Learn more

- Review [OAuth2 provider](./index.md) for enabling the provider and creating an application
- Review [Integration patterns](./integration-patterns.md) for client authentication methods and flows
- Review [Security and limitations](./security.md) for security considerations and current limitations

---

# OAuth2 provider security and limitations

Source: https://coder.com/docs/admin/integrations/oauth2-provider/security

This page covers security guidance and current limitations.

- [OAuth2 provider](./index.md): how to turn on the provider and create an application

## Security considerations

- **Use HTTPS**: Always use HTTPS in production to protect tokens in transit
- **Implement PKCE**: PKCE is mandatory for all authorization code clients (public and confidential)
- **Validate redirect URLs**: Only register trusted redirect URIs.
  Dangerous schemes (`javascript:`, `data:`, `file:`, `ftp:`) are blocked by the control plane, custom URI schemes for native apps (`myapp://`) are permitted, and public clients additionally cannot use `mailto:`, `tel:`, or `sms:`
- **Rotate secrets**: Periodically rotate client secrets using the management API
- **Rate limits**: every `/oauth2` endpoint and both `/.well-known` discovery endpoints draw on the login rate limit of 60 requests per minute.
  Each endpoint counts on its own, so a caller that exhausts one can still reach the others.
  Requests with no Coder session are counted per IP address, and the rest are counted per user.
  A caller over the limit receives HTTP 429 with a `temporarily_unavailable` error body.
  The limit is fixed.
  Running the deployment with `--dangerous-disable-rate-limits` turns it off, and a user with the Owner role can bypass it on a single request with the `X-Coder-Bypass-Ratelimit` header
- **Refresh tokens are not self-sufficient**: a confidential client must present its `client_secret` to refresh or revoke, so a leaked token alone cannot mint new access tokens or end another client's session
- **No CORS on the authorization endpoint**: `/oauth2/authorize` is reached only by browser navigation and sends no CORS headers, as OAuth 2.1 requires.
  The token, registration, revocation, and metadata endpoints do allow cross-origin requests so that browser-based clients can call them

## Limitations

The current implementation has these limitations:

- No client credentials grant support
- No device authorization grant support (RFC 8628)
- Implicit grant (`response_type=token`) is not supported; OAuth 2.1 deprecated this flow due to token leakage risks, and a request for it redirects to the registered callback with `unsupported_response_type`
- Limited to opaque access tokens (no JWT support)
- An application may register at most 32 redirect URIs of at most 2048 bytes each.
  An application that stored a longer list before this limit existed keeps working, but it cannot be saved again until the list fits.
  To fix it, send a `PUT` with a `redirect_uris` list that fits, as shown under [Create an application with the API](./index.md#create-an-application-with-the-api).
  In the web UI, open the application and remove entries from **Redirect URIs** until the list fits.
- A cleartext `http://` redirect URI to a host that is not local is rejected.
  Earlier versions accepted one through the management API for a confidential application, although Dynamic Client Registration always refused it.
  An application that stored one keeps working, but it cannot be saved again until its list uses `https://` or a local host, as described under [Callback URL schemes](./callback-url-schemes.md).
- A redirect URI with a private-use scheme must name a path or an authority, as described under [Callback URL schemes](./callback-url-schemes.md).
  Dynamic Client Registration accepted the bare form, such as `com.example.app:callback`, in earlier versions.
  A client that registered one can re-register with an accepted form, or an administrator can correct it with the same `PUT`.

## Learn more

- Review [OAuth2 provider](./index.md) for enabling the provider and creating an application
- Review [Integration patterns](./integration-patterns.md) for client authentication methods and flows
- Check [Troubleshooting](./troubleshooting.md) if you hit an error
- Refer to [Security Best Practices](../../security/index.md) for deployment security guidance

---

# Dev Containers

Source: https://coder.com/docs/admin/integrations/devcontainers

Dev containers allow developers to define their development environment
as code using the [Dev Container specification](https://containers.dev/).
Configuration lives in a `devcontainer.json` file alongside source code,
enabling consistent, reproducible environments.

By adopting dev containers, organizations can:

- **Standardize environments**: Eliminate "works on my machine" issues while
  still allowing developers to customize their tools within approved boundaries.
- **Scale efficiently**: Let developers maintain their own environment
  definitions, reducing the burden on platform teams.
- **Improve security**: Use hardened base images and controlled package
  registries to enforce security policies while enabling developer self-service.

Coder supports two approaches for running dev containers. Choose based on your
infrastructure and workflow requirements.

## Dev Containers Integration

The Dev Containers Integration uses the standard `@devcontainers/cli` and Docker
to run containers inside your workspace. This is the recommended approach for
most use cases.

**Best for:**

- Workspaces with Docker available (Docker-in-Docker or mounted socket)
- Dev container management in the Coder dashboard (discovery, status, rebuild)
- Multiple dev containers per workspace

[Configure Dev Containers Integration](./integration.md)

For user documentation, see the
[Dev Containers user guide](../../../user-guides/devcontainers/index.md).

## Envbuilder

Envbuilder transforms the workspace image itself from a `devcontainer.json`,
rather than running containers inside the workspace. It does not require
a Docker daemon.

**Best for:**

- Environments where Docker is unavailable or restricted
- Infrastructure-level control over image builds, caching, and security scanning
- Kubernetes-native deployments without privileged containers

[Configure Envbuilder](./envbuilder/index.md)

---

# Configure a template for Dev Containers

Source: https://coder.com/docs/admin/integrations/devcontainers/integration

This guide covers the Dev Containers Integration, which uses Docker. For
environments without Docker, see [Envbuilder](./envbuilder/index.md) as an
alternative.

To enable Dev Containers in workspaces, configure your template with the Dev Containers
modules and configurations outlined in this doc.

Dev Containers are currently not supported in Windows or macOS workspaces.

## Configuration Modes

There are two approaches to configuring Dev Containers in Coder:

### Manual Configuration

Use the [`coder_devcontainer`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/devcontainer) Terraform resource to explicitly define which Dev
Containers should be started in your workspace. This approach provides:

- Predictable behavior and explicit control
- Clear template configuration
- Easier troubleshooting
- Better for production environments

This is the recommended approach for most use cases.

### Project Discovery

Alternatively, enable automatic discovery of Dev Containers in Git repositories.
The agent scans for `devcontainer.json` files and surfaces them in the Coder UI.
See [Environment Variables](#environment-variables) for configuration options.

This approach is useful when developers frequently switch between repositories
or work with many projects, as it reduces template maintenance overhead.

## Install the Dev Containers CLI

Use the
[devcontainers-cli](https://registry.coder.com/modules/devcontainers-cli) module
to ensure the `@devcontainers/cli` is installed in your workspace:

```tf
module "devcontainers-cli" {
  count    = data.coder_workspace.me.start_count
  source   = "registry.coder.com/coder/devcontainers-cli/coder"
  agent_id = coder_agent.dev.id
}
```

Alternatively, install the devcontainer CLI manually in your base image.

## Configure Automatic Dev Container Startup

The
[`coder_devcontainer`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/devcontainer)
resource automatically starts a Dev Container in your workspace, ensuring it's
ready when you access the workspace:

```tf
resource "coder_devcontainer" "my-repository" {
  count            = data.coder_workspace.me.start_count
  agent_id         = coder_agent.dev.id
  workspace_folder = "/home/coder/my-repository"
}
```

The `workspace_folder` attribute must point to a valid project folder containing
a `devcontainer.json` file. Consider using the
[`git-clone`](https://registry.coder.com/modules/git-clone) module to ensure
your repository is cloned and ready for automatic startup.

For multi-repo workspaces, define multiple `coder_devcontainer` resources, each
pointing to a different repository. Each one runs as a separate sub-agent with
its own terminal and apps in the dashboard.

## Enable Dev Containers Integration

Dev Containers integration is **enabled by default** in Coder 2.24.0 and later.
You don't need to set any environment variables unless you want to change the
default behavior.

If you need to explicitly disable Dev Containers, set the
`CODER_AGENT_DEVCONTAINERS_ENABLE` environment variable to `false`:

```tf
resource "docker_container" "workspace" {
  count = data.coder_workspace.me.start_count
  image = "codercom/oss-dogfood:latest"
  env = [
    "CODER_AGENT_DEVCONTAINERS_ENABLE=false",  # Explicitly disable
    # ... Other environment variables.
  ]
  # ... Other container configuration.
}
```

See the [Environment Variables](#environment-variables) section below for more
details on available configuration options.

## Environment Variables

The following environment variables control Dev Container behavior in your
workspace. Both `CODER_AGENT_DEVCONTAINERS_ENABLE` and
`CODER_AGENT_DEVCONTAINERS_PROJECT_DISCOVERY_ENABLE` are **enabled by default**,
so you typically don't need to set them unless you want to explicitly disable
the feature.

### CODER_AGENT_DEVCONTAINERS_ENABLE

**Default: `true`** • **Added in: v2.24.0**

Enables the Dev Containers integration in the Coder agent.

The Dev Containers feature is enabled by default. You can explicitly disable it
by setting this to `false`.

### CODER_AGENT_DEVCONTAINERS_PROJECT_DISCOVERY_ENABLE

**Default: `true`** • **Added in: v2.25.0**

Enables automatic discovery of Dev Containers in Git repositories.

When enabled, the agent scans the configured working directory (set via the
`directory` attribute in `coder_agent`, typically the user's home directory) for
Git repositories. If the directory itself is a Git repository, it searches that
project. Otherwise, it searches immediate subdirectories for Git repositories.

For each repository found, the agent looks for `devcontainer.json` files in the
[standard locations](../../../user-guides/devcontainers/index.md#add-a-devcontainerjson)
and surfaces discovered Dev Containers in the Coder UI. Discovery respects
`.gitignore` patterns.

Set to `false` if you prefer explicit configuration via `coder_devcontainer`.

### CODER_AGENT_DEVCONTAINERS_DISCOVERY_AUTOSTART_ENABLE

**Default: `false`** • **Added in: v2.25.0**

Automatically starts Dev Containers discovered via project discovery.

When enabled, discovered Dev Containers will be automatically built and started
during workspace initialization. This only applies to Dev Containers found via
project discovery. Dev Containers defined with the `coder_devcontainer` resource
always auto-start regardless of this setting.

## Attach Resources to Dev Containers

You can attach
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app),
[`coder_script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/script),
and [`coder_env`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/env)
resources to a `coder_devcontainer` by referencing its `subagent_id` attribute
as the `agent_id`:

```tf
resource "coder_devcontainer" "my-repository" {
  count            = data.coder_workspace.me.start_count
  agent_id         = coder_agent.dev.id
  workspace_folder = "/home/coder/my-repository"
}

resource "coder_app" "code-server" {
  count        = data.coder_workspace.me.start_count
  agent_id     = coder_devcontainer.my-repository[0].subagent_id
  # ...
}

resource "coder_script" "dev-setup" {
  count        = data.coder_workspace.me.start_count
  agent_id     = coder_devcontainer.my-repository[0].subagent_id
  # ...
}

resource "coder_env" "my-var" {
  count    = data.coder_workspace.me.start_count
  agent_id = coder_devcontainer.my-repository[0].subagent_id
  # ...
}
```

This also enables using [Coder registry](https://registry.coder.com) modules
that depend on these resources inside dev containers, by passing the
`subagent_id` as the module's `agent_id`.

### Terraform-managed dev containers

When a `coder_devcontainer` has any `coder_app`, `coder_script`, or `coder_env`
resource attached, it becomes a **terraform-managed** dev container. This
changes how Coder handles the sub-agent:

- The sub-agent is pre-defined during Terraform provisioning rather than created
  dynamically.
- On dev container configuration changes, Coder updates the sub-agent in-place
  instead of deleting and recreating it.

### Interaction with devcontainer.json customizations

Terraform-defined resources and
[`devcontainer.json` customizations](../../../user-guides/devcontainers/customizing-dev-containers.md)
work together with some limitations. The `displayApps` settings from
`devcontainer.json` are applied to terraform-managed dev containers, so you can
control built-in app visibility (e.g., hide VS Code Insiders) via
`devcontainer.json` even when using Terraform resources.

However, custom `apps` defined in `devcontainer.json` are **not applied** to
terraform-managed dev containers. If you need custom apps, define them as
`coder_app` resources in Terraform instead.

## Per-Container Customizations

Developers can customize individual dev containers using the `customizations.coder`
block in their `devcontainer.json` file. Available options include:

- `ignore` — Hide a dev container from Coder completely
- `autoStart` — Control whether the container starts automatically (requires
  `CODER_AGENT_DEVCONTAINERS_DISCOVERY_AUTOSTART_ENABLE` to be enabled)
- `name` — Set a custom agent name
- `displayApps` — Control which built-in apps appear
- `apps` — Define custom applications

For the full reference, see
[Customizing dev containers](../../../user-guides/devcontainers/customizing-dev-containers.md).

## Complete Template Example

Here's a simplified template example that uses Dev Containers with manual
configuration:

```tf
terraform {
  required_providers {
    coder  = { source = "coder/coder" }
    docker = { source = "kreuzwerker/docker" }
  }
}

provider "coder" {}
data "coder_workspace" "me" {}
data "coder_workspace_owner" "me" {}

resource "coder_agent" "dev" {
  arch                    = "amd64"
  os                      = "linux"
  startup_script_behavior = "blocking"
  startup_script          = "sudo service docker start"
  shutdown_script         = "sudo service docker stop"
  # ...
}

module "devcontainers-cli" {
  count    = data.coder_workspace.me.start_count
  source   = "registry.coder.com/coder/devcontainers-cli/coder"
  agent_id = coder_agent.dev.id
}

resource "coder_devcontainer" "my-repository" {
  count            = data.coder_workspace.me.start_count
  agent_id         = coder_agent.dev.id
  workspace_folder = "/home/coder/my-repository"
}

# Attaching resources to dev containers is optional. By attaching
# this resource to the dev container, we are changing how the dev
# container will be treated by Coder. This limits the ability to
# customize the injected agent via the devcontainer.json file.
resource "coder_env" "env" {
  count    = data.coder_workspace.me.start_count
  agent_id = coder_devcontainer.my-repository[0].subagent_id
  name     = "MY_VAR"
  value    = "my-value"
}
```

### Alternative: Project Discovery with Autostart

By default, discovered containers appear in the dashboard but developers must
manually start them. To have them start automatically, enable autostart:

```tf
resource "docker_container" "workspace" {
  count = data.coder_workspace.me.start_count
  image = "codercom/oss-dogfood:latest"
  env = [
    # Project discovery is enabled by default, but autostart is not.
    # Enable autostart to automatically build and start discovered containers:
    "CODER_AGENT_DEVCONTAINERS_DISCOVERY_AUTOSTART_ENABLE=true",
    # ... Other environment variables.
  ]
  # ... Other container configuration.
}
```

With autostart enabled:

- Discovered containers automatically build and start during workspace
  initialization
- The `coder_devcontainer` resource is not required
- Developers can work with multiple projects seamlessly

> [!NOTE]
>
> When using project discovery, you still need to install the devcontainers CLI
> using the module or in your base image.

## Example Template

The [Docker (Dev Containers)](../../../../examples/templates/docker-devcontainer)
starter template demonstrates Dev Containers integration using Docker-in-Docker.
It includes the `devcontainers-cli` module, `git-clone` module, and the
`coder_devcontainer` resource.

## Next Steps

- [Dev Containers Integration](../../../user-guides/devcontainers/index.md)
- [Customizing Dev Containers](../../../user-guides/devcontainers/customizing-dev-containers.md)
- [Working with Dev Containers](../../../user-guides/devcontainers/working-with-dev-containers.md)
- [Troubleshooting Dev Containers](../../../user-guides/devcontainers/troubleshooting-dev-containers.md)

---

# Envbuilder

Source: https://coder.com/docs/admin/integrations/devcontainers/envbuilder

Envbuilder is an open-source tool that builds development environments from
[dev container](https://containers.dev/implementors/spec/) configuration files.
Unlike the [Dev Containers integration](../integration.md),
Envbuilder transforms the workspace image itself rather than running containers
inside the workspace.

Envbuilder is well-suited for Kubernetes-native deployments without privileged
containers, environments where Docker is unavailable or restricted, and
workflows where administrators need infrastructure-level control over image
builds, caching, and security scanning. For workspaces with Docker available,
the [Dev Containers Integration](../integration.md) offers container management
with dashboard visibility and multi-container support.

Dev containers provide developers with increased autonomy and control over their
Coder cloud development environments.

By using dev containers, developers can customize their workspaces with tools
pre-approved by platform teams in registries like
[JFrog Artifactory](../../jfrog-artifactory.md). This simplifies
workflows, reduces the need for tickets and approvals, and promotes greater
independence for developers.

## Prerequisites

An administrator should construct or choose a base image and create a template
that includes a `devcontainer_builder` image before a developer team configures
dev containers.

## Devcontainer Features

[Dev container Features](https://containers.dev/implementors/features/) allow
owners of a project to specify self-contained units of code and runtime
configuration that can be composed together on top of an existing base image.
This is a good place to install project-specific tools, such as
language-specific runtimes and compilers.

## Coder Envbuilder

[Envbuilder](https://github.com/coder/envbuilder/) is an open-source project
maintained by Coder that runs dev containers via Coder templates and your
underlying infrastructure. Envbuilder can run on Docker or Kubernetes.

It is independently packaged and versioned from the centralized Coder
open-source project. This means that Envbuilder can be used with Coder, but it
is not required. It also means that dev container builds can scale independently
of the Coder control plane and even run within a CI/CD pipeline.

## Next steps

- [Add an Envbuilder template](./add-envbuilder.md)

---

# Add an Envbuilder template

Source: https://coder.com/docs/admin/integrations/devcontainers/envbuilder/add-envbuilder

A Coder administrator adds an Envbuilder-compatible template to Coder. This
allows the template to prompt the developer for their dev container repository's
URL as a [parameter](../../../templates/extending-templates/parameters.md) when they create
their workspace. Envbuilder clones the repo and builds a container from the
`devcontainer.json` specified in the repo.

You can create template files through the Coder dashboard, CLI, or you can
choose a template from the
[Coder registry](https://registry.coder.com/templates):

<div class="tabs">

## Dashboard

1. In the Coder dashboard, select **Templates** > **New Template**.
   The template builder opens.
1. The template builder does not currently include dev-container-compatible base templates.
   Select **Upload an existing template** at the bottom of the page to upload your Terraform files directly.
1. Upload your `.zip` or `.tar.gz` file, enter the details, then select **Create template**.
1. Edit the template files to fit your deployment.

## CLI

1. Use the `template init` command to initialize your choice of image:

   ```sh
   coder template init --id kubernetes-devcontainer
   ```

   A list of available templates is shown in the
   [templates_init](../../../../reference/cli/templates/index.md) reference.

1. `cd` into the directory and push the template to your Coder deployment:

   ```sh
   cd kubernetes-devcontainer && coder templates push
   ```

   You can also edit the files or make changes to the files before you push them
   to Coder.

## Registry

1. Go to the [Coder registry](https://registry.coder.com/templates) and select a
   dev container-compatible template.

1. Copy the files to your local device, then edit them to fit your needs.

1. Upload them to Coder through the CLI or dashboard:

   - CLI:

   ```sh
   coder templates push <template-name> -d <path to folder containing main.tf>
   ```

   - Dashboard:

   1. Create a `.zip` of the template files:

      - On Mac or Windows, highlight the files and then right click. A
        "compress" option is available through the right-click context menu.

      - To zip the files through the command line:

        ```sh
        zip templates.zip Dockerfile main.tf
        ```

   1. Select **Templates**.
   1. Select **Create Template**, then **Upload template**:

      ![Upload template](../../../../images/templates/upload-create-your-first-template.png)

   1. Drag the `.zip` file into the **Upload template** section and fill out the
      details, then select **Create template**.

      ![Upload the template files](../../../../images/templates/upload-create-template-form.png)

</div>

To set variables such as the namespace, go to the template in your Coder
dashboard and select **Settings** from the **⋮** (vertical ellipsis) menu:

<img height="255px" src="../../../../images/templates/template-menu-settings.png" alt="Choose Settings from the template's menu" align="center" />

## Envbuilder Terraform provider

When using the
[Envbuilder Terraform provider](https://registry.terraform.io/providers/coder/envbuilder/latest/docs),
a previously built and cached image can be reused directly, allowing dev
containers to start instantaneously.

Developers can edit the `devcontainer.json` in their workspace to customize
their development environments:

```json
# …
{
  "features": {
      "ghcr.io/devcontainers/features/common-utils:2": {}
  }
}
# …
```

## Example templates

| Template                                                                                  | Description                                                                                                                                                         |
|-------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Docker dev containers](../../../../../examples/templates/docker-devcontainer)            | Docker provisions a development container.                                                                                                                          |
| [Kubernetes dev containers](../../../../../examples/templates/kubernetes-devcontainer)    | Provisions a development container on the Kubernetes cluster.                                                                                                       |
| [Google Compute Engine dev container](../../../../../examples/templates/gcp-devcontainer) | Runs a development container inside a single GCP instance. It also mounts the Docker socket from the VM inside the container to enable Docker inside the workspace. |
| [AWS EC2 dev container](../../../../../examples/templates/aws-devcontainer)               | Runs a development container inside a single EC2 instance. It also mounts the Docker socket from the VM inside the container to enable Docker inside the workspace. |

Your template can prompt the user for a repo URL with
[parameters](../../../templates/extending-templates/parameters.md):

![Dev container parameter screen](../../../../images/templates/devcontainers.png)

## Dev container lifecycle scripts

The `onCreateCommand`, `updateContentCommand`, `postCreateCommand`, and
`postStartCommand` lifecycle scripts are run each time the container is started.
This could be used, for example, to fetch or update project dependencies before
a user begins using the workspace.

Lifecycle scripts are managed by project developers.

## Next steps

- [Envbuilder security and caching](./envbuilder-security-caching.md)

---

# Envbuilder security and caching

Source: https://coder.com/docs/admin/integrations/devcontainers/envbuilder/envbuilder-security-caching

Ensure Envbuilder can only pull pre-approved images and artifacts by configuring
it with your existing HTTP proxies, firewalls, and artifact managers.

## Configure registry authentication

You may need to authenticate to your container registry, such as Artifactory, or
Git provider such as GitLab, to use Envbuilder. See the
[Envbuilder documentation](https://github.com/coder/envbuilder/blob/main/docs/container-registry-auth.md)
for more information.

## Layer and image caching

To improve build times, dev containers can be cached. There are two main forms
of caching:

- **Layer caching**

  - Caches individual layers and pushes them to a remote registry. When building
    the image, Envbuilder will check the remote registry for pre-existing layers
    These will be fetched and extracted to disk instead of building the layers
    from scratch.

- **Image caching**

  - Caches the entire image, skipping the build process completely (except for
    post-build
    [lifecycle scripts](./add-envbuilder.md#dev-container-lifecycle-scripts)).

Note that caching requires push access to a registry, and may require approval
from relevant infrastructure team(s).

Refer to the
[Envbuilder documentation](https://github.com/coder/envbuilder/blob/main/docs/caching.md)
for more information about Envbuilder and caching.

Visit the
[speed up templates](../../../../tutorials/best-practices/speed-up-templates.md)
best practice documentation for more ways that you can speed up build times.

### Image caching

To support resuming from a cached image, use the
[Envbuilder Terraform Provider](https://github.com/coder/terraform-provider-envbuilder)
in your template. The provider will:

1. Clone the remote Git repository,
1. Perform a "dry-run" build of the dev container in the same manner as
   Envbuilder would,
1. Check for the presence of a previously built image in the provided cache
   repository,
1. Output the image remote reference in SHA256 form, if it finds one.

The example templates listed above will use the provider if a remote cache
repository is provided.

If you are building your own Dev container template, you can consult the
[provider documentation](https://registry.terraform.io/providers/coder/envbuilder/latest/docs/resources/cached_image).
You may also wish to consult a
[documented example usage of the `envbuilder_cached_image` resource](https://github.com/coder/terraform-provider-envbuilder/blob/main/examples/resources/envbuilder_cached_image/envbuilder_cached_image_resource.tf).

## Next steps

- [Envbuilder releases and known issues](./envbuilder-releases-known-issues.md)
- [Dotfiles](../../../../user-guides/workspace-dotfiles.md)

---

# Envbuilder releases and known issues

Source: https://coder.com/docs/admin/integrations/devcontainers/envbuilder/envbuilder-releases-known-issues

## Release channels

Envbuilder provides two release channels:

- **Stable**
  - Available at
    [`ghcr.io/coder/envbuilder`](https://github.com/coder/envbuilder/pkgs/container/envbuilder).
    Tags `>=1.0.0` are considered stable.
- **Preview**
  - Available at
    [`ghcr.io/coder/envbuilder-preview`](https://github.com/coder/envbuilder/pkgs/container/envbuilder-preview).
    Built from the tip of `main`, and should be considered experimental and
    prone to breaking changes.

Refer to the
[Envbuilder GitHub repository](https://github.com/coder/envbuilder/) for more
information and to submit feature requests or bug reports.

## Known issues

Visit the
[Envbuilder repository](https://github.com/coder/envbuilder/blob/main/docs/devcontainer-spec-support.md)
for a full list of supported features and known issues.

---

# Networking

Source: https://coder.com/docs/admin/networking

Coder's network topology has three types of nodes: workspaces, the control
plane, and users.

The control plane must have an inbound address reachable by users and
workspaces, but otherwise, all topologies _just work_ with Coder.

When possible, we establish direct connections between users and workspaces.
Direct connections are as fast as connecting to the workspace outside of Coder.
When NAT traversal fails, connections are relayed through the control plane. All
user-workspace connections are end-to-end encrypted.

[Tailscale's open source](https://tailscale.com) backs our websocket/HTTPS
networking logic.

## Requirements

In order for clients and workspaces to be able to connect:

> [!NOTE]
> We strongly recommend that clients connect to Coder and their
> workspaces over a good quality, broadband network connection. The following
> are minimum requirements:
>
> - better than 400&nbsp;ms round-trip latency to the control plane and to their workspace
> - better than 0.5% random packet loss

- All clients and agents must be able to establish a connection to the control
  plane (`CODER_ACCESS_URL`) over HTTP/HTTPS.
- Any reverse proxy or ingress between the Coder control plane and
  clients/agents must support WebSockets.

In order for clients to be able to establish direct connections:

> [!NOTE]
> Direct connections via the web browser are not supported. To improve
> latency for browser-based applications running inside Coder workspaces in
> regions far from the Coder control plane, consider deploying one or more
> [workspace proxies](./workspace-proxies.md).

- The client is connecting using the CLI (e.g. `coder ssh` or
  `coder port-forward`). Note that the
  [VSCode extension](https://marketplace.visualstudio.com/items?itemName=coder.coder-remote)
  and [JetBrains Plugin](https://plugins.jetbrains.com/plugin/19620-coder/), and
  [`ssh coder.<workspace>`](../../reference/cli/config-ssh.md) all utilize the
  CLI to establish a workspace connection.
- Either the client or workspace agent are able to discover a reachable
  `ip:port` of their counterpart. If the agent and client are able to
  communicate with each other using their locally assigned IP addresses, then a
  direct connection can be established immediately. Otherwise, the client and
  agent will contact
  [the configured STUN servers](../../reference/cli/server/index.md#--derp-server-stun-addresses)
  to try and determine which `ip:port` can be used to communicate with their
  counterpart. See [STUN and NAT](./stun.md) for more details on how this
  process works.
- All outbound UDP traffic must be allowed for both the client and the agent on
  **all ports** to each others' respective networks.
  - To establish a direct connection, both agent and client use STUN. This
    involves sending UDP packets outbound on `udp/3478` to the configured
    [STUN server](../../reference/cli/server/index.md#--derp-server-stun-addresses).
    If either the agent or the client are unable to send and receive UDP packets
    to a STUN server, then direct connections will not be possible.
  - Both agents and clients will then establish a
    [WireGuard](https://www.wireguard.com/)️ tunnel and send UDP traffic on
    ephemeral (high) ports. If a firewall between the client and the agent
    blocks this UDP traffic, direct connections will not be possible.

## Control plane

Workspaces connect to the control plane via its external address, set
by [`ACCESS_URL`](../../admin/setup/index.md#access-url). There must not be a
NAT between workspaces and the control plane.

Users connect to the control plane's dashboard and API through its `ACCESS_URL`
as well. There must not be a NAT between users and the control plane.

Template admins can overwrite the site-wide access URL at the template level by
leveraging the `url` argument when
[defining the Coder provider](https://registry.terraform.io/providers/coder/coder/latest/docs#url-1):

```tf
provider "coder" {
  url = "https://coder.namespace.svc.cluster.local"
}
```

This is useful when debugging connectivity issues between the workspace agent
and the control plane.

## Web Apps

The control plane relays dashboard-initiated connections between the user and
the workspace. Web terminal <-> workspace connections are an exception and may
be direct.

In general, [port forwarded](./port-forwarding.md) web apps are faster than
dashboard-accessed web apps.

## 🌎 Geo-distribution

### Direct connections

Direct connections are a straight line between the user and workspace, so there
is no special geo-distribution configuration. To speed up direct connections,
move the user and workspace closer together.

Establishing a direct connection can be an involved process because both the
client and workspace agent will likely be behind at least one level of NAT,
meaning that we need to use STUN to learn the IP address and port under which
the client and agent can both contact each other. See [STUN and NAT](./stun.md)
for more information on how this process works.

If a direct connection is not available (e.g. client or server is behind NAT),
Coder will use a relayed connection. By default,
[Coder uses Google's public STUN server](../../reference/cli/server/index.md#--derp-server-stun-addresses),
but this can be disabled or changed for
[Air-gapped deployments](../../install/prepare/airgap.md).

### Relayed connections

By default, your control plane also runs a built-in DERP relay which can be used
for both public and [Air-gapped deployments](../../install/prepare/airgap.md).

However, Tailscale maintains a global fleet of [DERP relays](https://tailscale.com/kb/1118/custom-derp-servers/#what-are-derp-servers) intended for their product, and has allowed Coder to access and use them.
You can launch `coder server` with Tailscale's DERPs like so:

```sh
coder server --derp-config-url https://controlplane.tailscale.com/derpmap/default
```

#### Custom Relays

If you want lower latency than what Tailscale offers or want additional DERP
relays for air-gapped deployments, you may run custom DERP servers. Refer to
[Tailscale's documentation](https://tailscale.com/kb/1118/custom-derp-servers/#why-run-your-own-derp-server)
to learn how to set them up.

After you have custom DERP servers, you can launch Coder with them like so:

```json
# derpmap.json
{
  "Regions": {
    "1": {
      "RegionID": 1,
      "RegionCode": "myderp",
      "RegionName": "My DERP",
      "Nodes": [
        {
          "Name": "1",
          "RegionID": 1,
          "HostName": "your-hostname.com"
        }
      ]
    }
  }
}
```

```sh
coder server --derp-config-path derpmap.json
```

### Dashboard connections

The dashboard (and web apps opened through the dashboard) are served from the
control plane, so they can only be geo-distributed with High Availability mode
in our Premium Edition. [Reach out to Sales](https://coder.com/contact) to learn
more.

## Browser-only connections

> [!NOTE]
> Browser-only connections is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Some Coder deployments require that all access is through the browser to comply
with security policies. In these cases, pass the `--browser-only` flag to
`coder server` or set `CODER_BROWSER_ONLY=true`.

With browser-only connections, developers can only connect to their workspaces
via the web terminal and
[web IDEs](../../user-guides/workspace-access/web-ides.md).

### Workspace Proxies

> [!NOTE]
> Workspace proxies are a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Workspace proxies are a Coder Premium feature that allows you to provide
low-latency browser experiences for geo-distributed teams.

To learn more, see [Workspace Proxies](./workspace-proxies.md).

## Latency

Coder measures and reports several types of latency, providing insights into the performance of your deployment. Understanding these metrics can help you diagnose issues and optimize the user experience.

There are three main types of latency metrics for your Coder deployment:

- Dashboard-to-server latency:

  The Coder UI measures round-trip time to the control plane or workspace proxy using built-in browser timing capabilities.

  This appears in the user interface next to your username, showing how responsive the dashboard is.

- Workspace connection latency:

  The latency shown on the workspace dashboard measures the round-trip time between the workspace agent and its DERP relay server.

  This metric is displayed in milliseconds on the workspace dashboard and specifically shows the agent-to-relay latency, not direct P2P connections.

  To estimate the total end-to-end latency experienced by a user, add the dashboard-to-server latency to this agent-to-relay latency.

- Database latency:

  For administrators, Coder monitors and reports database query performance in the health dashboard.

### How latency is classified

Latency measurements are color-coded in the dashboard:

- **Green** (<150&nbsp;ms): Good performance.
- **Yellow** (150-300&nbsp;ms): Moderate latency that might affect user experience.
- **Red** (>300&nbsp;ms): High latency that will noticeably affect user experience.

### View latency information

- **Dashboard**: The global latency indicator appears in the top navigation bar.
- **Workspace list**: Each workspace shows its connection latency.
- **Health dashboard**: Administrators can view advanced metrics including database latency.
- **CLI**: Use `coder ping <workspace>` to measure and analyze latency from the command line.

### Factors that affect latency

- **Geographic distance**: Physical distance between users, the control plane, and workspaces.
- **Network connectivity**: Quality of internet connections and routing.
- **Infrastructure**: Cloud provider regions and network optimization.
- **P2P connectivity**: Whether direct connections can be established or relays are needed.

### How to optimize latency

To improve latency and user experience:

- **Deploy workspace proxies**: Place [proxies](./workspace-proxies.md) in regions closer to users, connecting back to your single control plane deployment.
- **Use P2P connections**: Ensure network configurations permit direct connections.
- **Strategic placement**: Deploy your control plane in a region where most users work.
- **Network configuration**: Optimize routing between users and workspaces.
- **Check firewall rules**: Ensure they don't block necessary Coder connections.

For help troubleshooting connection issues, including latency problems, refer to the [networking troubleshooting guide](./troubleshooting.md).

## External Network Access

By default, Coder will access some external network endpoints in order to download dependencies and send usage data. However, all of these features can be disabled. Learn how to configure Coder for [air-gapped environments](../../install/prepare/airgap.md).

## Up next

- Learn about [Port Forwarding](./port-forwarding.md)
- Troubleshoot [Networking Issues](./troubleshooting.md)

---

# Port Forwarding

Source: https://coder.com/docs/admin/networking/port-forwarding

Port forwarding lets developers securely access processes on their Coder
workspace from a local machine. A common use case is testing web applications in
a browser.

There are four ways to forward ports in Coder:

| Method                                 | Details                                                                                                                                                        |
|:---------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Coder Desktop](#coder-desktop)        | Automatic port forwarding via VPN tunnel. All workspace ports are available at `workspace.coder:PORT` with no manual setup. Supports peer-to-peer connections. |
| [CLI](#the-coder-port-forward-command) | Forwards specific TCP or UDP ports from the workspace to local ports. Supports peer-to-peer connections.                                                       |
| [Dashboard](#dashboard)                | Proxies traffic through the Coder control plane.                                                                                                               |
| [SSH](#ssh)                            | Forwards ports over an SSH connection.                                                                                                                         |

Coder Desktop and `coder port-forward` are generally more performant than:

1. The Dashboard which proxies traffic through the Coder control plane versus
   peer-to-peer which is possible with the Coder CLI and Coder Desktop
1. `sshd` which does double encryption of traffic with both Wireguard and SSH

## Coder Desktop

[Coder Desktop](../../user-guides/desktop/index.md) provides automatic port forwarding to every service running in your workspace.
Once Coder Connect is enabled, any port your application listens on is instantly accessible at `<workspace-name>.coder:PORT` from your local machine, with no additional commands or configuration.

This is the simplest option for most users. See the [Coder Desktop documentation](../../user-guides/desktop/index.md) for installation and setup.

## The `coder port-forward` command

This command can be used to forward TCP or UDP ports from the remote workspace
so they can be accessed locally. Both the TCP and UDP command line flags
(`--tcp` and `--udp`) can be given once or multiple times.

The supported syntax variations for the `--tcp` and `--udp` flag are:

- Single port with optional remote port: `local_port[:remote_port]`
- Comma separation `local_port1,local_port2`
- Port ranges `start_port-end_port`
- Any combination of the above

### Examples

Forward the remote TCP port `8080` to local port `8000`:

```console
coder port-forward myworkspace --tcp 8000:8080
```

Forward the remote TCP port `3000` and all ports from `9990` to `9999` to their
respective local ports.

```console
coder port-forward myworkspace --tcp 3000,9990-9999
```

Forward the remote TCP port `3000` and all ports from `9990` to `9999` to their
respective local ports to the `agent` in your Workspace (typically main or dev).
This is needed when you have multiple agents in your workspace.

```console
coder port-forward myworkspace.agent --tcp 3000,9990-9999
```

For more examples, see `coder port-forward --help`.

## Dashboard

To enable port forwarding via the dashboard, Coder must be configured with a
[wildcard access URL](../../admin/setup/index.md#wildcard-access-url). If an
access URL is not specified, Coder will create
[a publicly accessible URL](../../admin/setup/index.md#tunnel) to reverse
proxy the deployment, and port forwarding will work.

There is a
[DNS limitation](https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.1)
where each segment of hostnames must not exceed 63 characters. If your app
name, agent name, workspace name and username exceed 63 characters in the
hostname, port forwarding via the dashboard will not work.

### From a coder_app resource

One way to port forward is to configure a `coder_app` resource in the
workspace's template. This approach shows a visual application icon in the
dashboard. See the following `coder_app` example for a Node React app and note
the `subdomain` and `share` settings:

```tf
# node app
resource "coder_app" "node-react-app" {
  agent_id  = coder_agent.dev.id
  slug      = "node-react-app"
  icon      = "https://upload.wikimedia.org/wikipedia/commons/a/a7/React-icon.svg"
  url       = "http://localhost:3000"
  subdomain = true
  share     = "authenticated"

  healthcheck {
    url       = "http://localhost:3000/healthz"
    interval  = 10
    threshold = 30
  }

}
```

Valid `share` values include `owner` - private to the user, `authenticated` -
accessible by any user authenticated to the Coder deployment, and `public` -
accessible by users outside of the Coder deployment.

![Port forwarding from an app in the UI](../../images/networking/portforwarddashboard.png)

<a id="accessing-workspace-ports"></a>

## Access workspace ports

Another way to port forward in the dashboard is to use the "Open Ports" button
to specify an arbitrary port. Coder will also detect if apps inside the
workspace are listening on ports, and list them below the port input (this is
only supported on Windows and Linux workspace agents).

![Port forwarding in the UI](../../images/networking/listeningports.png)

<a id="sharing-ports"></a>

### Share ports

We allow developers to share ports as URLs, either with other authenticated
coder users or publicly. Using the open ports interface, developers can assign a
sharing levels that match our `coder_app`’s share option in
[Coder terraform provider](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app#share-1).

- `owner` (Default): The implicit sharing level for all listening ports, only
  visible to the workspace owner
- `authenticated`: Accessible by other authenticated Coder users on the same
  deployment.
- `public`: Accessible by any user with the associated URL.

Once a port is shared at either `authenticated` or `public` levels, it will stay
pinned in the open ports UI for better accessibility regardless of whether or
not it is still accessible.

![Annotated port controls in the UI](../../images/networking/annotatedports.png)

The sharing level is limited by the maximum level enforced in the template
settings in premium deployments, and not restricted in OSS deployments.

This can also be used to change the sharing level of `coder_app`s by entering
their port number in the sharable ports UI. The `share` attribute on `coder_app`
resource uses a different method of authentication and **is not impacted by the
template's maximum sharing level**, nor the level of a shared port that points
to the app.

### Configure maximum port sharing level

> [!NOTE]
> Configuring port sharing level is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Premium-licensed template admins can control the maximum port sharing level for
workspaces under a given template in the template settings. By default, the
maximum sharing level is set to `Owner`, meaning port sharing is disabled for
end-users. OSS deployments allow all workspaces to share ports at both the
`authenticated` and `public` levels.

![Max port sharing level in the UI](../../images/networking/portsharingmax.png)

<a id="configuring-port-protocol"></a>

### Configure port protocol

Both listening and shared ports can be configured to use either `HTTP` or
`HTTPS` to connect to the port. For listening ports the protocol selector
applies to any port you input or select from the menu. Shared ports have
protocol configuration for each shared port individually.

You can access any port on the workspace and can configure the port protocol
manually by appending a `s` to the port in the URL.

```txt
# Uses HTTP
https://33295--agent--workspace--user--apps.example.com/
# Uses HTTPS
https://33295s--agent--workspace--user--apps.example.com/
```

### Cross-origin resource sharing (CORS)

When forwarding via the dashboard, Coder automatically sets headers that allow
requests between separately forwarded applications belonging to the same user.

When forwarding through other methods the application itself will need to set
its own CORS headers if they are being forwarded through different origins since
Coder does not intercept these cases. See below for the required headers.

#### Authentication

Since ports forwarded through the dashboard are private, cross-origin requests
must include credentials (set `credentials: "include"` if using `fetch`) or the
requests cannot be authenticated and you will see an error resembling the
following:

```txt
Access to fetch at
'<https://coder.example.com/api/v2/applications/auth-redirect>' from origin
'<https://8000--dev--user--apps.coder.example.com>' has been blocked by CORS
policy: No 'Access-Control-Allow-Origin' header is present on the requested
resource. If an opaque response serves your needs, set the request's mode to
'no-cors' to fetch the resource with CORS disabled.
```

#### Headers

Below is a list of the cross-origin headers Coder sets with example values:

```txt
access-control-allow-credentials: true
access-control-allow-methods: PUT
access-control-allow-headers: X-Custom-Header
access-control-allow-origin: https://8000--dev--user--apps.coder.example.com
vary: Origin
vary: Access-Control-Request-Method
vary: Access-Control-Request-Headers
```

The allowed origin will be set to the origin provided by the browser if the
users are identical. Credentials are allowed and the allowed methods and headers
will echo whatever the request sends.

#### Configuration

These cross-origin headers are not configurable by administrative settings.

If applications set any of the above headers they will be stripped from the
response except for `Vary` headers that are set to a value other than the ones
listed above.

In other words, CORS behavior through the dashboard is not currently
configurable by either admins or users.

#### Allowed by default

<table class="tg">
<thead>
  <tr>
    <th class="tg-0pky" rowspan="2"></th>
    <th class="tg-0pky" rowspan="3"></th>
    <th class="tg-0pky">From</th>
    <th class="tg-0pky" colspan="3">Alice</th>
    <th class="tg-0pky">Bob</th>
  </tr>
  <tr>
    <th class="tg-0pky" rowspan="2"></th>
    <th class="tg-0pky">Workspace 1</th>
    <th class="tg-0pky" colspan="2">Workspace 2</th>
    <th class="tg-0pky">Workspace 3</th>
  </tr>
  <tr>
    <th class="tg-0pky">To</th>
    <th class="tg-0pky">App A</th>
    <th class="tg-0pky">App B</th>
    <th class="tg-0pky">App C</th>
    <th class="tg-0pky">App D</th>
  </tr>
</thead>
<tbody>
  <tr>
    <td class="tg-0pky" rowspan="3">Alice</td>
    <td class="tg-0pky" rowspan="2">Workspace 1</td>
    <td class="tg-0pky">App A</td>
    <td class="tg-0pky">✅</td>
    <td class="tg-0pky">✅<span style="font-weight:400;font-style:normal">*</span></td>
    <td class="tg-0pky">✅<span style="font-weight:400;font-style:normal">*</span></td>
    <td class="tg-0pky">❌</td>
  </tr>
  <tr>
    <td class="tg-0pky">App B</td>
    <td class="tg-0pky">✅*</td>
    <td class="tg-0pky">✅</td>
    <td class="tg-0pky">✅<span style="font-weight:400;font-style:normal">*</span></td>
    <td class="tg-0pky">❌</td>
  </tr>
  <tr>
    <td class="tg-0pky">Workspace 2</td>
    <td class="tg-0pky">App C</td>
    <td class="tg-0pky">✅<span style="font-weight:400;font-style:normal">*</span></td>
    <td class="tg-0pky">✅<span style="font-weight:400;font-style:normal">*</span></td>
    <td class="tg-0pky">✅</td>
    <td class="tg-0pky">❌</td>
  </tr>
  <tr>
    <td class="tg-0pky">Bob</td>
    <td class="tg-0pky">Workspace 3</td>
    <td class="tg-0pky">App D</td>
    <td class="tg-0pky">❌</td>
    <td class="tg-0pky">❌</td>
    <td class="tg-0pky">❌</td>
    <td class="tg-0pky">✅</td>
  </tr>
</tbody>
</table>

> '\*' means `credentials: "include"` is required

## SSH

First,
[configure SSH](../../user-guides/workspace-access/index.md#configure-ssh) on
your local machine. Then, use `ssh` to forward like so:

```console
ssh -L 8080:localhost:8000 coder.myworkspace
```

You can read more on SSH port forwarding
[here](https://www.ssh.com/academy/ssh/tunneling/example).

---

# STUN and NAT

Source: https://coder.com/docs/admin/networking/stun

[Session Traversal Utilities for NAT (STUN)](https://www.rfc-editor.org/rfc/rfc8489.html)
is a protocol used to assist applications in establishing peer-to-peer
communications across Network Address Translations (NATs) or firewalls.

[Network Address Translation (NAT)](https://en.wikipedia.org/wiki/Network_address_translation)
is commonly used in private networks to allow multiple devices to share a
single public IP address. The vast majority of home and corporate internet
connections use at least one level of NAT.

## Overview

In order for one application to connect to another across a network, the
connecting application needs to know the IP address and port under which the
target application is reachable. If both applications reside on the same
network, then they can most likely connect directly to each other. In the
context of a Coder workspace agent and client, this is generally not the case,
as both agent and client will most likely be running in different _private_
networks (e.g. `192.168.1.0/24`). In this case, at least one of the two will
need to know an IP address and port under which they can reach their
counterpart.

This problem is often referred to as NAT traversal, and Coder uses a standard
protocol named STUN to address this.

Inside of that network, packets from the agent or client will show up as having
source address `192.168.1.X:12345`. However, outside of this private network,
the source address will show up differently (for example, `12.3.4.56:54321`). In
order for the Coder client and agent to establish a direct connection with each
other, one of them needs to know the `ip:port` pair under which their
counterpart can be reached. Once communication succeeds in one direction, we can
inspect the source address of the received packet to determine the return
address.

> [!TIP]
> The below glosses over a lot of the complexity of traversing NATs.
> For a more in-depth technical explanation, see
> [How NAT traversal works (tailscale.com)](https://tailscale.com/blog/how-nat-traversal-works).

At a high level, STUN works like this:

- **Discovery:** Both the client and agent will send UDP traffic to one or more
  configured STUN servers. These STUN servers are generally located on the
  public internet, and respond with the public IP address and port from which
  the request came.
- **Coordination:** The client and agent then exchange this information through
  the control plane. They will then construct packets that should be able to
  successfully traverse their counterpart's NATs successfully.
- **NAT Traversal:** The client and agent then send these crafted packets to
  their counterpart's public addresses. If all goes well, the NATs on the other
  end should route these packets to the correct internal address.
- **Connection:** Once the packets reach the other side, they send a response
  back to the source `ip:port` from the packet. Again, the NATs should recognize
  these responses as belonging to an ongoing communication, and forward them
  accordingly.

At this point, both the client and agent should be able to send traffic directly
to each other.

## Examples

### 1. Direct connections without NAT or STUN

In this example, both the client and agent are located on the network
`192.168.21.0/24`. Assuming no firewalls are blocking packets in either
direction, both client and agent are able to communicate directly with each
other's locally assigned IP address.

![Diagram of a workspace agent and client in the same network](../../images/networking/stun1.png)

### 2. Direct connections with one layer of NAT

In this example, client and agent are located on different networks and connect
to each other over the public Internet. Both client and agent connect to a
configured STUN server located on the public Internet to determine the public IP
address and port on which they can be reached.

![Diagram of a workspace agent and client in separate networks](../../images/networking/stun2.1.png)

They then exchange this information through the control plane, and can then
communicate directly with each other through their respective NATs.

![Diagram of a workspace agent and client in separate networks](../../images/networking/stun2.2.png)

### 3. Direct connections with VPN and NAT hairpinning

In this example, the client workstation must use a VPN to connect to the
corporate network. All traffic from the client will enter through the VPN entry
node and exit at the VPN exit node inside the corporate network. Traffic from
the client inside the corporate network will appear to be coming from the IP
address of the VPN exit node `172.16.1.2`. Traffic from the client to the public
internet will appear to have the public IP address of the corporate router
`12.34.56.7`.

The workspace agent is running on a Kubernetes cluster inside the corporate
network, which is behind its own layer of NAT. To anyone inside the corporate
network but outside the cluster network, its traffic will appear to be coming
from `172.16.1.254`. However, traffic from the agent to services on the public
Internet will also see traffic originating from the public IP address assigned
to the corporate router. Additionally, the corporate router will most likely
have a firewall configured to block traffic from the internet to the corporate
network.

If the client and agent both use the public STUN server, the addresses
discovered by STUN will both be the public IP address of the corporate router.
To correctly route the traffic backwards, the corporate router must correctly
route both:

- Traffic sent from the client to the external IP of the corporate router back
  to the cluster router, and
- Traffic sent from the agent to the external IP of the corporate router to the
  VPN exit node.

This behaviour is known as "hairpinning", and may not be supported in all
network configurations.

If hairpinning is not supported, deploying an internal STUN server can aid
establishing direct connections between client and agent. When the agent and
client query this internal STUN server, they will be able to determine the
addresses on the corporate network from which their traffic appears to
originate. Using these internal addresses is much more likely to result in a
successful direct connection.

![Diagram of a workspace agent and client over VPN](../../images/networking/stun3.png)

## Hard NAT

Some NATs are known to use a different port when forwarding requests to the STUN
server and when forwarding probe packets to peers. In that case, the address a
peer discovers over the STUN protocol will have the correct IP address, but the
wrong port. Tailscale refers to this as "hard" NAT in
[How NAT traversal works (tailscale.com)](https://tailscale.com/blog/how-nat-traversal-works).

If both peers are behind a "hard" NAT, direct connections may take longer to
establish or will not be established at all. If one peer is behind a "hard" NAT
and the other is running a firewall (including Windows Defender Firewall), the
firewall may block direct connections.

In both cases, peers fallback to DERP connections if they cannot establish a
direct connection.

If your workspaces are behind a "hard" NAT, you can:

1. Ensure clients are not also behind a "hard" NAT. You may have limited ability
   to control this if end users connect from their homes.
2. Ensure firewalls on client devices (e.g. Windows Defender Firewall) have an
   inbound policy allowing all UDP ports either to the `coder` or `coder.exe`
   CLI binary, or from the IP addresses of your workspace NATs.
3. Reconfigure your workspace network's NAT connection to the public internet to
   be an "easy" NAT. See below for specific examples.

### AWS NAT Gateway

The
[AWS NAT Gateway](https://docs.aws.amazon.com/vpc/latest/userguide/vpc-nat-gateway.html)
is a known "hard" NAT. You can use a
[NAT Instance](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_NAT_Instance.html)
instead of a NAT Gateway, and configure it to use the same port assignment for
all UDP traffic from a particular source IP:port combination (Tailscale calls
this "easy" NAT). Linux `MASQUERADE` rules work well for this.

### AWS Elastic Kubernetes Service (EKS)

The default configuration of AWS Elastic Kubernetes Service (EKS) includes the
[Amazon VPC CNI Driver](https://github.com/aws/amazon-vpc-cni-k8s), which by
default randomizes the public port for different outgoing UDP connections. This
makes it act as a "hard" NAT, even if the EKS nodes are on a public subnet (and
thus do not need to use the AWS NAT Gateway to reach the Internet).

This behavior can be disabled by setting the environment variable
`AWS_VPC_K8S_CNI_RANDOMIZESNAT=none` in the `aws-node` DaemonSet. Note, however,
if your nodes are on a private subnet, they will still need NAT to reach the
public Internet, meaning that issues with the
[AWS NAT Gateway](#aws-nat-gateway) might affect you.

---

# Workspace proxies (Premium)

Source: https://coder.com/docs/admin/networking/workspace-proxies

Workspace proxies provide low-latency experiences for geo-distributed teams.

> [!NOTE]
> Workspace proxies require a
> [Premium license](https://coder.com/pricing#compare-plans).
> For more details, [contact your account team](https://coder.com/contact).

Coder's networking does a best effort to make direct connections to a workspace.
In situations where this is not possible, such as connections via the web
terminal and
[web IDEs](../../user-guides/workspace-access/index.md#other-web-ides),
workspace proxies are able to reduce the amount of distance the network traffic
needs to travel.

A workspace proxy is a relay connection a developer can choose to use when
connecting with their workspace over SSH, a workspace app, port forwarding, etc.
Dashboard connections and API calls (e.g. the workspaces list) are not served
over workspace proxies.

## Deploy a workspace proxy

Each workspace proxy should be a unique instance. At no point should two
workspace proxy instances share the same authentication token. They only require
port 443 to be open and are expected to have network connectivity to the control
plane dashboard. Workspace proxies **do not** make any database connections.

Workspace proxies can be used in the browser by navigating to the user
`Account -> Workspace Proxy`

## Requirements

- The [Coder CLI](../../reference/cli/index.md) must be installed and
  authenticated as a user with the Owner role.

## Step 1: Create the proxy

Create the workspace proxy and make sure to save the returned authentication
token for said proxy. This is the token the workspace proxy will use to
authenticate back to primary coderd.

```sh
$ coder wsproxy create --name=newyork --display-name="USA East" --icon="/emojis/2194.png"
Workspace Proxy "newyork" created successfully. Save this token, it will not be shown again.
Token: 2fb6500b-bb47-4783-a0db-dedde895b865:05271b4ef9432bac14c02b3c56b5a2d7f05453718a1f85ba7e772c0a096c7175
```

To verify it was created.

```sh
$ coder wsproxy ls
NAME         URL                    STATUS STATUS
newyork                             unregistered
```

## Step 2: Deploy the proxy

Deploying the workspace proxy will also register the proxy with the control
plane and make the workspace proxy usable. If the proxy deployment is
successful, `coder wsproxy ls` will show an `ok` status code:

```sh
$ coder wsproxy ls
NAME              URL                         STATUS STATUS
primary           https://dev.coder.com        ok
brazil-saopaulo   https://brazil.example.com   ok
europe-frankfurt  https://europe.example.com   ok
sydney            https://sydney.example.com   ok
```

Other Status codes:

- `unregistered` : The workspace proxy was created, and not yet deployed
- `unreachable` : The workspace proxy was registered, but is not responding.
  Likely the proxy went offline.
- `unhealthy` : The workspace proxy is reachable, but has some issue that is
  preventing the proxy from being used. `coder wsproxy ls` should show the error
  message.
- `ok` : The workspace proxy is healthy and working properly!

### Configuration

Workspace proxy configuration overlaps with a subset of the `coderd`
configuration. To see the full list of configuration options:
`coder wsproxy server --help`

```sh
# Proxy specific configuration. These are REQUIRED
# Example: https://coderd.example.com
CODER_PRIMARY_ACCESS_URL="https://<url_of_coderd_dashboard>"
CODER_PROXY_SESSION_TOKEN="<session_token_from_proxy_create>"

# Runtime variables for "coder start".
CODER_HTTP_ADDRESS=0.0.0.0:80
CODER_TLS_ADDRESS=0.0.0.0:443
# Example: https://east.coderd.example.com
CODER_ACCESS_URL="https://<access_url_of_proxy>"
# Example: *.east.coderd.example.com
CODER_WILDCARD_ACCESS_URL="*.<app_hostname_of_proxy>"

CODER_TLS_ENABLE=true
CODER_TLS_CLIENT_AUTH=none
CODER_TLS_CERT_FILE="<cert_file_location>"
CODER_TLS_KEY_FILE="<key_file_location>"

# Additional configuration options are available.
```

<a id="running-on-kubernetes"></a>

### Run on Kubernetes

Make a `values-wsproxy.yaml` with the workspace proxy configuration.

Notice the `workspaceProxy` configuration which is `false` by default in the
Coder Helm chart:

```yaml
coder:
  env:
    - name: CODER_PRIMARY_ACCESS_URL
      value: "https://<url_of_coderd_dashboard>"
    - name: CODER_PROXY_SESSION_TOKEN
      value: "<session_token_from_proxy_create>"
    # Example: https://east.coderd.example.com
    - name: CODER_ACCESS_URL
      value: "https://<access_url_of_proxy>"
    # Example: *.east.coderd.example.com
    - name: CODER_WILDCARD_ACCESS_URL
      value: "*.<app_hostname_of_proxy>"

  tls:
    secretNames:
      - kubernetes-wsproxy-secret

  # enable workspace proxy
  workspaceProxy: true
```

Using Helm, install the workspace proxy chart

```sh
helm install coder coder-v2/coder --namespace <your workspace proxy namespace> -f ./values-wsproxy.yaml
```

Test that the workspace proxy is reachable with `curl -vvv`. If for some reason,
the Coder dashboard still shows the workspace proxy is `UNHEALTHY`, scale down
and up the deployment's replicas.

<a id="running-on-a-vm"></a>

### Run on a VM

```sh
# Set configuration options via environment variables, a config file, or cmd flags
coder wsproxy server
```

<a id="running-as-a-system-service"></a>

### Run as a system service

If you've installed Coder via a [system package](../../install/index.md), you
can configure the workspace proxy by settings in
`/etc/coder.d/coder-workspace-proxy.env`

To run workspace proxy as a system service on the host:

```sh
# Use systemd to start workspace proxy now and on reboot
sudo systemctl enable --now coder-workspace-proxy

# View the logs to ensure a successful start
journalctl -u coder-workspace-proxy.service -b
```

To restart workspace proxy after applying system changes:

```sh
sudo systemctl restart coder-workspace-proxy
```

<a id="running-in-docker"></a>

### Run in Docker

Modify the default entrypoint to run a workspace proxy server instead of a
regular control plane.

#### Docker Compose

Change the provided
[`compose.yml`](../../../compose.yaml)
file to include a custom entrypoint:

```diff
  image: ghcr.io/coder/coder:${CODER_VERSION:-latest}
+ entrypoint: /opt/coder wsproxy server
```

#### Docker run

```sh
docker run --rm -it --entrypoint /opt/coder ghcr.io/coder/coder:latest wsproxy server
```

#### Custom Dockerfile

```dockerfile
FROM ghcr.io/coder/coder:latest
ENTRYPOINT ["/opt/coder", "wsproxy", "server"]
```

<a id="selecting-a-proxy"></a>

### Select a proxy

Users can select a workspace proxy at the top-right of the browser-based Coder dashboard.
Workspace proxy preferences are cached by the web browser.
If a proxy goes offline, the session will fall back to the primary proxy.
This could take up to 60&nbsp;seconds.

![Workspace proxy picker](../../images/admin/networking/workspace-proxies/ws-proxy-picker.png)

## Multiple workspace proxies

When multiple workspace proxies are deployed:

- The browser measures latency to each available proxy independently.
- Users can select their preferred proxy from the dashboard.
- The system can automatically select the lowest-latency proxy.
- The dashboard latency indicator shows latency to the currently selected proxy.

## Observability

Coder workspace proxy exports metrics via the HTTP endpoint, which can be
enabled using either the environment variable `CODER_PROMETHEUS_ENABLE` or the
flag `--prometheus-enable`.

The Prometheus endpoint address is `http://localhost:2112/` by default. You can
use either the environment variable `CODER_PROMETHEUS_ADDRESS` or the flag
`--prometheus-address <network-interface>:<port>` to select a different listen
address.

---

# High Availability

Source: https://coder.com/docs/admin/networking/high-availability

High Availability (HA) mode solves for horizontal scalability and automatic
failover within a single region. When in HA mode, Coder continues using a single
Postgres endpoint.
[GCP](https://cloud.google.com/sql/docs/postgres/high-availability),
[AWS](https://docs.aws.amazon.com/prescriptive-guidance/latest/saas-multitenant-managed-postgresql/availability.html),
and other cloud vendors offer fully-managed HA Postgres services that pair
nicely with Coder.

For Coder to operate correctly, `coderd` instances should have low-latency
connections to each other so that they can effectively relay traffic between
users and workspaces no matter which `coderd` instance users or workspaces
connect to. We make a best-effort attempt to warn the user when inter-`coderd`
latency is too high, but if requests start dropping, this is one metric to
investigate.

We also recommend that you deploy all `coderd` instances such that they have
low-latency connections to Postgres. `coderd` often makes several database
round-trips while processing a single API request, so prioritizing low-latency
between `coderd` and Postgres is more important than low-latency between users
and `coderd`.

Note that this latency requirement applies _only_ to Coder services. Coder will
operate correctly even with few seconds of latency on workspace <-> Coder and
user <-> Coder connections.

## Setup

Coder automatically enters HA mode when multiple instances simultaneously
connect to the same Postgres endpoint.

> [!NOTE]
> When upgrading HA deployments, database migrations may require special
> handling to avoid lock contention. See
> [Upgrading Best Practices](../../install/operate/upgrade/best-practices.md) for
> recommended procedures.

HA brings one configuration variable to set in each `coderd` node:
`CODER_DERP_SERVER_RELAY_URL`. The HA nodes use these URLs to communicate with
each other. Inter-node communication is only required while using the embedded
relay (default). If you're using [custom relays](./index.md#custom-relays),
Coder ignores `CODER_DERP_SERVER_RELAY_URL` since Postgres is the sole
rendezvous for the Coder nodes.

`CODER_DERP_SERVER_RELAY_URL` will never be `CODER_ACCESS_URL` because
`CODER_ACCESS_URL` is a load balancer to all Coder nodes.

Coder also clusters its inter-node pubsub across HA nodes and needs each
replica's routable address to do so. This address comes from
`CODER_CLUSTER_HOST`, falling back to the host in `CODER_DERP_SERVER_RELAY_URL`
when it is unset. Set `CODER_CLUSTER_HOST` to each node's routable IP address.
Setting it is required when you use [custom relays](./index.md#custom-relays),
because `CODER_DERP_SERVER_RELAY_URL` is ignored and no fallback address is
available. If a node has neither value set, Coder logs an error and falls back
to PostgreSQL for pubsub.

Here's an example 3-node network configuration setup:

| Name      | `CODER_HTTP_ADDRESS` | `CODER_DERP_SERVER_RELAY_URL` | `CODER_CLUSTER_HOST` | `CODER_ACCESS_URL`       |
|-----------|----------------------|-------------------------------|----------------------|--------------------------|
| `coder-1` | `*:80`               | `http://10.0.0.1:80`          | `10.0.0.1`           | `https://coder.big.corp` |
| `coder-2` | `*:80`               | `http://10.0.0.2:80`          | `10.0.0.2`           | `https://coder.big.corp` |
| `coder-3` | `*:80`               | `http://10.0.0.3:80`          | `10.0.0.3`           | `https://coder.big.corp` |

## Kubernetes

If you installed Coder via
[our Helm Chart](../../install/server/kubernetes/index.md#4-install-coder-with-helm), just
increase `coder.replicaCount` in `values.yaml`.

If you installed Coder into Kubernetes by some other means, insert the relay URL
via the environment like so:

```yaml
env:
  - name: POD_IP
    valueFrom:
      fieldRef:
        fieldPath: status.podIP
  - name: CODER_DERP_SERVER_RELAY_URL
    value: http://$(POD_IP)
  - name: CODER_CLUSTER_HOST
    value: $(POD_IP)
```

Then, increase the number of pods.

## Up next

- [Read more on Coder's networking stack](./index.md)
- [Install on Kubernetes](../../install/server/kubernetes/index.md)

---

# Wildcard access URLs

Source: https://coder.com/docs/admin/networking/wildcard-access-url

Wildcard access URLs unlock Coder's full potential for modern development workflows. While optional for basic SSH usage, this feature becomes essential when teams need web applications, development previews, or browser-based tools. **Wildcard access URLs are essential for many development workflows in Coder** - Web IDEs (code-server, VS Code Web, JupyterLab) and some development frameworks work significantly better with subdomain-based access rather than path-based URLs.

## Why configure wildcard access URLs?

### Key benefits

- **Enables port access**: Each application gets a unique subdomain with [port support](https://coder.com/docs/user-guides/workspace-access/port-forwarding#dashboard) (e.g. `8080--main--myworkspace--john.coder.example.com`).
- **Enhanced security**: Applications run in isolated subdomains with separate browser security contexts and prevents access to the Coder API from malicious JavaScript
- **Better compatibility**: Most applications are designed to work at the root of a hostname rather than at a subpath, making subdomain access more reliable

### Applications that require subdomain access

The following tools require wildcard access URL:

- **Vite dev server**: Hot module replacement and asset serving issues with path-based routing
- **React dev server**: Similar issues with hot reloading and absolute path references
- **Next.js development server**: Asset serving and routing conflicts with path-based access
- **JupyterLab**: More complex template configuration and security risks when using path-based routing
- **RStudio**: More complex template configuration and security risks when using path-based routing

## Configuration

`CODER_WILDCARD_ACCESS_URL` is necessary for [port forwarding](port-forwarding.md#dashboard) via the dashboard or running [coder_apps](../templates/index.md) on an absolute path.
Set it to a wildcard hostname that resolves to Coder.
The value must contain exactly one `*` at the beginning of the hostname.
Coder replaces `*` with the generated application name, which stays within a single DNS label.

Coder supports the wildcard as a full label or with a suffix in the first label:

| Pattern              | Example generated application hostname           | Required DNS and TLS wildcard |
|----------------------|--------------------------------------------------|-------------------------------|
| `*.apps.example.com` | `8080--main--myworkspace--john.apps.example.com` | `*.apps.example.com`          |
| `*-apps.example.com` | `8080--main--myworkspace--john-apps.example.com` | `*.example.com`               |

For example, use the suffix pattern to keep the Coder dashboard and application hostnames at the same DNS level:

```dotenv
CODER_ACCESS_URL=https://apps.example.com
CODER_WILDCARD_ACCESS_URL=*-apps.example.com
```

This configuration serves the dashboard from `https://apps.example.com` and a workspace application from a hostname such as `https://8080--main--myworkspace--john-apps.example.com`.

### TLS Certificate Setup

Wildcard access URLs require a TLS certificate that covers the wildcard domain. You have several options:

> [!TIP]
> You can use a single certificate for both the access URL and wildcard access URL.
> For `*.apps.example.com`, the certificate must include `apps.example.com` and `*.apps.example.com`.
> For `*-apps.example.com` with an access URL of `apps.example.com`, a certificate for `*.example.com` covers both hostnames.

#### Direct TLS Configuration

Configure Coder to handle TLS directly using the wildcard certificate:

```sh
export CODER_TLS_ENABLE=true
export CODER_TLS_CERT_FILE=/path/to/wildcard.crt
export CODER_TLS_KEY_FILE=/path/to/wildcard.key
```

See [TLS & Reverse Proxy](../setup/index.md#tls--reverse-proxy) for detailed configuration options.

#### Reverse Proxy with Let's Encrypt

Use a reverse proxy to handle TLS termination with automatic certificate management:

- [NGINX with Let's Encrypt](../../tutorials/reverse-proxy-nginx.md)
- [Apache with Let's Encrypt](../../tutorials/reverse-proxy-apache.md)
- [Caddy reverse proxy](../../tutorials/reverse-proxy-caddy.md)

If your reverse proxy rewrites the request `Host` and forwards the original
host in `X-Forwarded-Host`, configure
[`CODER_PROXY_TRUSTED_ORIGINS`](../../reference/cli/server/index.md#--proxy-trusted-origins)
to trust that proxy's address. Otherwise Coder will ignore `X-Forwarded-Host`
for subdomain app routing.

### DNS Setup

You'll need to configure DNS to point wildcard subdomains to your control plane:

> [!NOTE]
> We do not recommend using a top-level-domain for Coder wildcard access
> (for example `*.workspaces`), even on private networks with split-DNS. Some
> browsers consider these "public" domains and will refuse Coder's cookies,
> which are vital to the proper operation of this feature.

```txt
*.coder.example.com    A    <your-coder-server-ip>
```

Or alternatively, using a CNAME record:

```txt
*.coder.example.com    CNAME    coder.example.com
```

For a suffix pattern such as `*-apps.example.com`, DNS and TLS wildcards must cover the entire first label:

```txt
*.example.com    A    <your-coder-server-ip>
```

DNS providers and certificate authorities don't interpret `*-apps.example.com` as a wildcard record or certificate name.
Configure `*.example.com` instead, and ensure routing that wildcard to Coder doesn't conflict with other services under `example.com`.

### Workspace Proxies

If you're using [workspace proxies](workspace-proxies.md) for geo-distributed teams, each proxy requires its own wildcard access URL configuration:

```sh
# Main control plane
export CODER_WILDCARD_ACCESS_URL="*.coder.example.com"

# Sydney workspace proxy
export CODER_WILDCARD_ACCESS_URL="*.sydney.coder.example.com"

# London workspace proxy
export CODER_WILDCARD_ACCESS_URL="*.london.coder.example.com"
```

Each proxy's wildcard domain must have corresponding DNS records:

```txt
*.sydney.coder.example.com    A    <sydney-proxy-ip>
*.london.coder.example.com    A    <london-proxy-ip>
```

## Template Configuration

In your Coder templates, enable subdomain applications using the `subdomain` parameter:

```tf
resource "coder_app" "code-server" {
  agent_id     = coder_agent.main.id
  slug         = "code-server"
  display_name = "VS Code"
  url          = "http://localhost:8080"
  icon         = "/icon/code.svg"
  subdomain    = true
  share        = "owner"
}
```

## Troubleshooting

### Applications not accessible

If workspace applications are not working:

1. Verify the `CODER_WILDCARD_ACCESS_URL` environment variable is configured correctly:
   - Check the deployment settings in the Coder dashboard (Settings > Deployment)
   - Ensure it matches your wildcard domain (e.g., `*.coder.example.com`)
   - Restart the control plane if you made changes to the environment variable
2. Check DNS resolution for wildcard subdomains:

   ```sh
   dig test.coder.example.com
   nslookup test.coder.example.com
   ```

3. Ensure TLS certificates cover the wildcard domain
4. Confirm template `coder_app` resources have `subdomain = true`

## See also

- [Workspace Proxies](workspace-proxies.md) - Improve performance for geo-distributed teams using wildcard URLs

---

# Troubleshooting

Source: https://coder.com/docs/admin/networking/troubleshooting

`coder ping <workspace>` will ping the workspace agent and print diagnostics on
the state of the connection. These diagnostics are created by inspecting both
the client and agent network configurations, and provide insights into why a
direct connection may be impeded, or why the quality of one might be degraded.

The `-v/--verbose` flag can be appended to the command to print client debug
logs.

```console
$ coder ping dev
pong from workspace proxied via  DERP(Council Bluffs, Iowa)  in 42ms
pong from workspace proxied via  DERP(Council Bluffs, Iowa)  in 41ms
pong from workspace proxied via  DERP(Council Bluffs, Iowa)  in 39ms
✔ preferred DERP region: 999 (Council Bluffs, Iowa)
✔ sent local data to Coder networking coordinator
✔ received remote agent data from Coder networking coordinator
    preferred DERP region: 999 (Council Bluffs, Iowa)
    endpoints: x.x.x.x:46433, x.x.x.x:46433, x.x.x.x:46433
✔ Wireguard handshake 11s ago

❗ You are connected via a DERP relay, not directly (p2p)
Possible client-side issues with direct connection:
 - Network interface utun0 has MTU 1280, (less than 1378), which may degrade the quality of direct connections

Possible agent-side issues with direct connection:
 - Agent is potentially behind a hard NAT, as multiple endpoints were retrieved from different STUN servers
 - Agent IP address is within an AWS range (AWS uses hard NAT)
```

## Common Problems with Direct Connections

### Disabled Deployment-wide

Direct connections can be disabled at the deployment level by setting the
`CODER_BLOCK_DIRECT` environment variable or the `--block-direct-connections`
flag on the control plane. When set, this will be reflected in the output of
`coder ping`.

### UDP Blocked

Some corporate firewalls block UDP traffic. Direct connections require UDP
traffic to be allowed between the client and agent, as well as between the
client/agent and STUN servers in most cases. `coder ping` will indicate if
either the Coder agent or client had issues sending or receiving UDP packets to
STUN servers.

If this is the case, you may need to add exceptions to the firewall to allow UDP
for Coder workspaces, clients, and STUN servers.

### Endpoint-Dependent NAT (Hard NAT)

Hard NATs prevent public endpoints gathered from STUN servers from being used by
the peer to establish a direct connection. Typically, if only one side of the
connection is behind a hard NAT, direct connections can still be established
easily. However, if both sides are behind hard NATs, direct connections may take
longer to establish or may not be possible at all.

`coder ping` will indicate if it's possible the client or agent is behind a hard
NAT.

Learn more about [STUN and NAT](./stun.md).

### No STUN Servers

If there are no STUN servers available within a deployment's DERP MAP, direct
connections may not be possible. Notable exceptions are if the client and agent
are on the same network, or if either is able to use UPnP instead of STUN to
resolve the public IP of the other. `coder ping` will indicate if no STUN
servers were found.

### Endpoint Firewalls

Direct connections may also be impeded if one side is behind a hard NAT and the
other is running a firewall that blocks ingress traffic from unknown 5-tuples
(Protocol, Source IP, Source Port, Destination IP, Destination Port).

If this is suspected, you may need to add an exception for Coder to the
firewall, or reconfigure the hard NAT.

### VPNs

If a VPN is the default route for all IP traffic, it may interfere with the
ability for clients and agents to form direct connections. This happens if the
NAT does not permit traffic to be
['hairpinned'](./stun.md#3-direct-connections-with-vpn-and-nat-hairpinning) from
the public IP address of the NAT (determined via STUN) to the internal IP
address of the agent.

If this is the case, you may need to add exceptions to the VPN for Coder, modify
the NAT configuration, or deploy an internal STUN server.

### Low MTU

If a network interface on the side of either the client or agent has an MTU
smaller than 1378, any direct connections form may have degraded quality or
might hang entirely.

Use `coder ping` to check for MTU issues, as it inspects
network interfaces on both the client and the workspace agent:

```console
$ coder ping my-workspace
...
Possible client-side issues with direct connection:

 - Network interface utun0 has MTU 1280 (less than 1378), which may degrade the quality of direct connections or render them unusable.
```

If another interface cannot be used, and the MTU cannot be changed, you should
disable direct connections and relay all traffic via DERP instead, which
will not be affected by the low MTU.

To disable direct connections, set the
[`--block-direct-connections`](../../reference/cli/server/index.md#--block-direct-connections)
flag or `CODER_BLOCK_DIRECT` environment variable on the control plane.

## Throughput

The `coder speedtest <workspace>` command measures the throughput between the
client and the workspace agent.

```console
$ coder speedtest workspace
29ms via coder
Starting a 5s download test...
INTERVAL       TRANSFER         BANDWIDTH
0.00-1.00 sec  630.7840 MBits   630.7404 Mbits/sec
1.00-2.00 sec  913.9200 MBits   913.8106 Mbits/sec
2.00-3.00 sec  943.1040 MBits   943.0399 Mbits/sec
3.00-4.00 sec  933.3760 MBits   933.2143 Mbits/sec
4.00-5.00 sec  848.8960 MBits   848.7019 Mbits/sec
5.00-5.02 sec  13.5680 MBits    828.8189 Mbits/sec
----------------------------------------------------
0.00-5.02 sec  4283.6480 MBits  853.8217 Mbits/sec
```

---

# Monitor Coder

Source: https://coder.com/docs/admin/monitoring

Learn about our the tools, techniques, and best practices to monitor your Coder
deployment.

## Quick Start: Observability Helm Chart

Deploy Prometheus, Grafana, Alert Manager, and pre-built dashboards on your
Kubernetes cluster to monitor the Coder control plane, provisioners, and
workspaces.

![Grafana Dashboard](../../images/admin/monitoring/grafana-dashboard.png)

Learn how to install & read the docs on the
[Observability Helm Chart GitHub](https://github.com/coder/observability)

## Table of Contents

- [Logs](./logs.md): Learn how to access `coderd` logs, agent logs, and
  even how to expose Kubernetes pod scheduling logs.
- [Metrics](./metrics.md): Learn about the valuable metrics to measure on a
  Coder deployment, regardless of your monitoring stack.
- [Health Check](./health-check.md): Learn about the periodic health check and
  error codes that run on Coder deployments.
- [Connection Logs](./connection-logs.md): Monitor connections to workspaces.

---

# Logs

Source: https://coder.com/docs/admin/monitoring/logs

All Coder services log to standard output, which can be critical for identifying
errors and monitoring Coder's deployment health. Like any service, logs can be
captured via Splunk, Datadog, Grafana Loki, or other ingestion tools.

## `coderd` Logs

By default, `coderd`, the process that runs the control plane, exports
human-readable logs to standard output. You can access these logs via
`kubectl logs deployment/coder -n <coder-namespace>`
on Kubernetes or `journalctl -u coder` if you deployed Coder on a host
machine/VM.

- To change the log format/location, you can set
  [`CODER_LOGGING_HUMAN`](../../reference/cli/server/index.md#--log-human) and
  [`CODER_LOGGING_JSON`](../../reference/cli/server/index.md#--log-json) server config.
  options.
- To only display certain types of logs, use
  the[`CODER_LOG_FILTER`](../../reference/cli/server/index.md#-l---log-filter) server
  config. Using `.*` will result in the `DEBUG` log level being used.

> [!NOTE]
> To disable human-readable logging, set `--log-human` (or
> `CODER_LOGGING_HUMAN`) to `/dev/null`. An empty string does not disable
> logging.

Events such as server errors, audit logs, user activities, and SSO & OpenID
Connect logs are all captured in the `coderd` logs.

## `provisionerd` Logs

Logs for [external provisioners](../../install/operate/provisioners/index.md) are structured
[and configured](../../reference/cli/provisioner/start.md#--log-human) similarly
to `coderd` logs. Use these logs to troubleshoot and monitor the Terraform
operations behind workspaces and templates.

## Workspace Logs

The [Coder agent](../../install/plan/architecture.md#agents) inside workspaces
provides useful logs around workspace-to-server and client-to-workspace
connections. For Kubernetes workspaces, these are typically the pod logs as the
agent runs via the container entrypoint.

Agent logs are also stored in the workspace filesystem by default:

- macOS/Linux: `/tmp/coder-agent.log`
- Windows: Refer to the template code (e.g.
  [azure-windows](https://github.com/coder/coder/blob/2cfadad023cb7f4f85710cff0b21ac46bdb5a845/examples/templates/azure-windows/Initialize.ps1.tftpl#L64))
  to see where logs are stored.

> [!NOTE]
> Logs are truncated once they reach 5&nbsp;MB in size.

Startup script logs are also stored in the temporary directory of macOS and
Linux workspaces.

## Kubernetes Event Logs

Sometimes, a workspace may take a while to start or even fail to start due to
underlying events on the Kubernetes cluster such as a node being out of
resources or a missing image. You can install
[coder-logstream-kube](../integrations/kubernetes-logs.md) to stream Kubernetes
events to the Coder UI.

![Kubernetes logs in Coder dashboard](../../images/admin/monitoring/logstream-kube.png)

---

# Deployment metrics

Source: https://coder.com/docs/admin/monitoring/metrics

Coder exposes many metrics which give insight into the current state of a live
Coder deployment. Our metrics are designed to be consumed by a
[Prometheus server](https://prometheus.io/).

If you don't have an Prometheus server installed, you can follow the Prometheus
[Getting started](https://prometheus.io/docs/prometheus/latest/getting_started/)
guide.

<a id="setting-up-metrics"></a>

## Set up metrics

To set up metrics monitoring, please read our
[Prometheus integration guide](../integrations/prometheus.md). The following
links point to relevant sections there.

- [Enable Prometheus metrics](../integrations/prometheus.md#enable-prometheus-metrics)
  in the control plane
- [Enable the Prometheus endpoint in Helm](../integrations/prometheus.md#kubernetes-deployment)
  (Kubernetes users only)
- [Configure Prometheus to scrape Coder metrics](../integrations/prometheus.md#prometheus-configuration)
- [See the list of available metrics](../integrations/prometheus.md#available-metrics)

---

# Deployment health

Source: https://coder.com/docs/admin/monitoring/health-check

Coder includes an operator-friendly deployment health page that provides a
number of details about the health of your Coder deployment.

![Health check in Coder Dashboard](../../images/admin/monitoring/health-check.png)

You can view it at `https://${CODER_URL}/health`, or you can alternatively view
the
[JSON response directly](../../reference/api/debug.md#debug-info-deployment-health).

The deployment health page is broken up into the following sections:

## Access URL

The Access URL section shows checks related to Coder's
[access URL](../setup/index.md#access-url).

Coder will periodically send a GET request to `${CODER_ACCESS_URL}/healthz` and
validate that the response is `200 OK`. The expected response body is also the
string `OK`.

If there is an issue, you may see one of the following errors reported:

### EACS01

### Access URL not set

**Problem:** no access URL has been configured.

**Solution:** configure an [access URL](../setup/index.md#access-url) for Coder.

### EACS02

#### Access URL invalid

**Problem:** `${CODER_ACCESS_URL}/healthz` is not a valid URL.

**Solution:** Ensure that the access URL is a valid URL accepted by
[`url.Parse`](https://pkg.go.dev/net/url#Parse). Example:
`https://dev.coder.com/`.

You can use [the Go playground](https://go.dev/play/p/CabcJZyTwt9) for additional testing.

### EACS03

#### Failed to fetch `/healthz`

**Problem:** Coder was unable to execute a GET request to
`${CODER_ACCESS_URL}/healthz`.

This could be due to a number of reasons, including but not limited to:

- DNS lookup failure
- A misconfigured firewall
- A misconfigured reverse proxy
- Invalid or expired SSL certificates

**Solution:** Investigate and resolve the root cause of the connection issue.

To troubleshoot further, you can log into the machine running Coder and attempt
to run the following command:

```sh
curl -v ${CODER_ACCESS_URL}/healthz
# Expected output:
# *   Trying XXX.XXX.XXX.XXX:443
# * Connected to https://coder.company.com (XXX.XXX.XXX.XXX) port 443 (#0)
# [...]
# OK
```

The output of this command should aid further diagnosis.

### EACS04

#### /healthz did not return 200 OK

**Problem:** Coder was able to execute a GET request to
`${CODER_ACCESS_URL}/healthz`, but the response code was not `200 OK` as
expected.

This could mean, for instance, that:

- The request did not actually hit your Coder instance (potentially an incorrect
  DNS entry)
- The request hit your Coder instance, but on an unexpected path (potentially a
  misconfigured reverse proxy)

**Solution:** Inspect the `HealthzResponse` in the health check output. This
should give you a good indication of the root cause.

## Database

Coder continuously executes a short database query to validate that it can reach
its configured database, and also measures the median latency over 5 attempts.

### EDB01

#### Database Ping Failed

**Problem:** This error code is returned if any attempt to execute this database
query fails.

**Solution:** Investigate the health of the database.

### EDB02

#### Database Latency High

**Problem:** This code is returned if the median latency is higher than the
[configured threshold](../../reference/cli/server/index.md#--health-check-threshold-database).
This may not be an error as such, but is an indication of a potential issue.

**Solution:** Investigate the sizing of the configured database with regard to
Coder's current activity and usage. It may be necessary to increase the
resources allocated to Coder's database. Alternatively, you can raise the
configured threshold to a higher value (this will not address the root cause).

> [!TIP]
> You can enable
> [detailed database metrics](../../reference/cli/server/index.md#--prometheus-collect-db-metrics)
> in Coder's Prometheus endpoint. If you have
> [tracing enabled](../../reference/cli/server/index.md#--trace), these traces may also
> contain useful information regarding Coder's database activity.

## DERP

Coder workspace agents may use
[DERP (Designated Encrypted Relay for Packets)](https://tailscale.com/blog/how-tailscale-works/#encrypted-tcp-relays-derp)
to communicate with Coder. This requires connectivity to a number of configured
[DERP servers](../../reference/cli/server/index.md#--derp-config-path) which are used
to relay traffic between Coder and workspace agents. Coder periodically queries
the health of its configured DERP servers and may return one or more of the
following:

### EDERP01

#### DERP Node Uses Websocket

**Problem:** When Coder attempts to establish a connection to one or more DERP
servers, it sends a specific `Upgrade: derp` HTTP header. Some load balancers
may block this header, in which case Coder will fall back to
`Upgrade: websocket`.

This is not necessarily a fatal error, but a possible indication of a
misconfigured reverse HTTP proxy. Additionally, while workspace users should
still be able to reach their workspaces, connection performance may be degraded.

> [!NOTE]
> This may also be shown if you have
> [forced websocket connections for DERP](../../reference/cli/server/index.md#--derp-force-websockets).

**Solution:** ensure that any proxies you use allow connection upgrade with the
`Upgrade: derp` header.

### EDERP02

#### One or more DERP nodes are unhealthy

**Problem:** This is shown if Coder is unable to reach one or more configured
DERP servers. Clients will fall back to use the remaining DERP servers, but
performance may be impacted for clients closest to the unhealthy DERP server.

**Solution:** Ensure that the DERP server is available and reachable over the
network, for example:

```sh
curl -v "https://coder.company.com/derp"
# Expected output:
# *   Trying XXX.XXX.XXX.XXX
# * Connected to https://coder.company.com (XXX.XXX.XXX.XXX) port 443 (#0)
# DERP requires connection upgrade
```

### EDERP03

#### No DERP servers available

**Problem:** This is shown when Coder's effective DERP map does not contain
any DERP servers. Without at least one working DERP server, workspace
networking may not work.

This can happen if the built-in DERP server is disabled and no external DERP
map is configured, or if workspace proxies are expected to provide DERP but no
healthy DERP-enabled proxy is currently available.

**Solution:** Ensure that at least one DERP server is available to the
deployment. For example:

- Restart `coderd` with the built-in DERP server enabled
- Restart `coderd` with an external DERP map configured
- Make sure a workspace proxy with DERP server enabled is running and healthy

### ESTUN01

#### No STUN servers available

**Problem:** This is shown if no STUN servers are available. Coder will use STUN
to establish [direct connections](../networking/stun.md). Without at least one
working STUN server, direct connections may not be possible.

**Solution:** Ensure that the
[configured STUN severs](../../reference/cli/server/index.md#--derp-server-stun-addresses)
are reachable from Coder and that UDP traffic can be sent/received on the
configured port.

### ESTUN02

#### STUN returned different addresses; you may be behind a hard NAT

**Problem:** This is a warning shown when multiple attempts to determine our
public IP address/port via STUN resulted in different `ip:port` combinations.
This is a sign that you are behind a "hard NAT", and may result in difficulty
establishing direct connections. However, it does not mean that direct
connections are impossible.

**Solution:** Engage with your network administrator.

## Websocket

Coder makes heavy use of [WebSockets](https://datatracker.ietf.org/doc/rfc6455/)
for long-lived connections:

- Between users interacting with Coder's Web UI (for example, the built-in
  terminal, or VSCode Web),
- Between workspace agents and `coderd`,
- Between Coder [workspace proxies](../networking/workspace-proxies.md) and
  `coderd`.

Any issues causing failures to establish WebSocket connections will result in
**severe** impairment of functionality for users. To validate this
functionality, Coder will periodically attempt to establish a WebSocket
connection with itself using the configured [Access URL](#access-url), send a
message over the connection, and attempt to read back that same message.

### EWS01

#### Failed to establish a WebSocket connection

**Problem:** Coder was unable to establish a WebSocket connection over its own
Access URL.

**Solution:** There are multiple possible causes of this problem:

1. Ensure that Coder's configured Access URL can be reached from the server
   running Coder, using standard troubleshooting tools like `curl`:

   ```sh
   curl -v "https://coder.company.com"
   ```

2. Ensure that any reverse proxy that is serving Coder's configured access URL
   allows connection upgrade with the header `Upgrade: websocket`.

### EWS02

#### Failed to echo a WebSocket message

**Problem:** Coder was able to establish a WebSocket connection, but was unable
to write a message.

**Solution:** There are multiple possible causes of this problem:

1. Validate that any reverse proxy servers in front of Coder's configured access
   URL are not prematurely closing the connection.
2. Validate that the network link between Coder and the workspace proxy is
   stable, e.g. by using `ping`.
3. Validate that any internal network infrastructure (for example, firewalls,
   proxies, VPNs) do not interfere with WebSocket connections.

## Workspace Proxy

If you have configured [Workspace Proxies](../networking/workspace-proxies.md),
Coder will periodically query their availability and show their status here.

### EWP01

#### Error Updating Workspace Proxy Health

**Problem:** Coder was unable to query the connected workspace proxies for their
health status.

**Solution:** This may be a transient issue. If it persists, it could signify a
connectivity issue.

### EWP02

#### Error Fetching Workspace Proxies

**Problem:** Coder was unable to fetch the stored workspace proxy health data
from the database.

**Solution:** This may be a transient issue. If it persists, it could signify an
issue with Coder's configured database.

### EWP04

#### One or more Workspace Proxies Unhealthy

**Problem:** One or more workspace proxies are not reachable.

**Solution:** Ensure that Coder can establish a connection to the configured
workspace proxies.

### EPD01

#### No Provisioner Daemons Available

**Problem:** No provisioner daemons are registered with Coder. No workspaces can
be built until there is at least one provisioner daemon running.

**Solution:**

If you are using
[External Provisioner Daemons](../../install/operate/provisioners/index.md), ensure
that they are able to successfully connect to Coder. Otherwise, ensure
[`--provisioner-daemons`](../../reference/cli/server/index.md#--provisioner-daemons)
is set to a value greater than 0.

> [!NOTE]
> This may be a transient issue if you are currently in the process of updating your deployment.

### EPD02

#### Provisioner Daemon Version Mismatch

**Problem:** One or more provisioner daemons are more than one major or minor
version out of date with the main deployment. It is important that provisioner
daemons are updated at the same time as the main deployment to minimize the risk
of API incompatibility.

**Solution:** Update the provisioner daemon to match the currently running
version of Coder.

> [!NOTE]
> This may be a transient issue if you are currently in the process of updating your deployment.

### EPD03

#### Provisioner Daemon API Version Mismatch

**Problem:** One or more provisioner daemons are using APIs that are marked as
deprecated. These deprecated APIs may be removed in a future release of Coder,
at which point the affected provisioner daemons will no longer be able to
connect to Coder.

**Solution:** Update the provisioner daemon to match the currently running
version of Coder.

> [!NOTE]
> This may be a transient issue if you are currently in the process of updating your deployment.

### EUNKNOWN

#### Unknown Error

**Problem:** This error is shown when an unexpected error occurred evaluating
deployment health. It may resolve on its own.

**Solution:** This may be a bug.
[File a GitHub issue](https://github.com/coder/coder/issues/new)!

---

# Connection logs (Premium)

Source: https://coder.com/docs/admin/monitoring/connection-logs

> [!NOTE]
> Connection logs require a
> [Premium license](https://coder.com/pricing#compare-plans).
> For more details, [contact your account team](https://coder.com/contact).

The **Connection Log** page in the dashboard allows Auditors to monitor workspace agent connections.

## Workspace App Connections

The connection log contains a complete record of all workspace app connections.
These originate from within the Coder deployment, and thus the connection log
is a source of truth for these events.

## Browser Port Forwarding

The connection log contains a complete record of all workspace port forwarding
performed via the dashboard.

## SSH and IDE Sessions

The connection log aims to capture a record of all workspace SSH and IDE sessions.
These events are reported by workspace agents, and their receipt by the control
plane is not guaranteed.

Agent-reported events do not identify the Coder user who connected. To
attribute SSH and IDE activity to a user, correlate them with tunnel
events for the same workspace and agent.

## Tunnel Connections

The connection log records the authorization decision for each request to add a tunnel to a workspace agent.
Accepted requests have status code `101`, and denied requests have status code `403`.
Tunnel events include the authenticated user's identity, IP address, and user agent.

Keep the following in mind when interpreting tunnel events:

- A tunnel event records an authorization decision, not how the tunnel was used.
  Clients such as `coder ssh`, `coder port-forward`, `coder ping`, `coder speedtest`, Coder Desktop, and IDE extensions can request tunnels.
- Tunnel events are deduplicated per workspace agent, actor, IP address, client, and authorization result.
  Clients automatically re-request tunnels after network interruptions or server restarts.
  These requests do not produce new events while a session is active.
  A new event is recorded after one hour of inactivity, or when the actor, IP address, client, or result changes.
- Like workspace app connections, tunnel events are point-in-time records.
  They have no close time and are excluded from `status:` filter results.

## How to Filter Connection Logs

You can filter connection logs by the following parameters:

- `organization` - The name or ID of the organization of the workspace being
     connected to.
- `workspace_owner` - The username of the owner of the workspace being connected
    to.
- `type` - The type of the connection, such as SSH, VS Code, or workspace app.
    For more connection types, refer to the
    [CoderSDK documentation](https://pkg.go.dev/github.com/coder/coder/v2/codersdk#ConnectionType).
- `username`: The name of the user who initiated the connection.
   Results do not include agent-reported SSH or IDE sessions.
- `user_email`: The email of the user who initiated the connection.
   Results do not include agent-reported SSH or IDE sessions.
- `connected_after`: The time after which the connection started.
   Uses the RFC3339Nano format.
- `connected_before`: The time before which the connection started.
   Uses the RFC3339Nano format.
- `workspace_id`: The ID of the workspace being connected to.
- `connection_id`: The ID of the connection.
- `status`: The status of the connection, either `ongoing` or `completed`.
     Some events are neither ongoing nor completed, such as the opening of a
     workspace app.

<a id="capturingexporting-connection-logs"></a>

## Capture and export connection logs

In addition to the Coder dashboard, there are multiple ways to consume or query
connection events.

### REST API

You can retrieve connection logs via the Coder API.
Visit the
[`get-connection-logs` endpoint documentation](../../reference/api/enterprise.md#get-connection-logs)
for details.

### Service Logs

Connection events are also dispatched as service logs and can be captured and
categorized using any log management tool such as [Splunk](https://splunk.com).

Example of a [JSON formatted](../../reference/cli/server/index.md#--log-json)
connection log entry, when an SSH connection is made:

```json
{
    "ts": "2025-07-03T05:09:41.929840747Z",
    "level": "INFO",
    "msg": "connection_log",
    "caller": "/home/coder/coder/enterprise/audit/backends/slog.go:38",
    "func": "github.com/coder/coder/v2/enterprise/audit/backends.(*SlogExporter).ExportStruct",
    "logger_names": ["coderd"],
    "fields": {
        "request_id": "916ad077-e120-4861-8640-f449d56d2bae",
        "ID": "ca5dfc63-dc43-463a-bb3e-38526866fd4b",
        "OrganizationID": "1a2bb67e-0117-4168-92e0-58138989a7f5",
        "WorkspaceOwnerID": "fe8f4bab-3128-41f1-8fec-1cc0755affe5",
        "WorkspaceID": "05567e23-31e2-4c00-bd05-4d499d437347",
        "WorkspaceName": "dev",
        "AgentName": "main",
        "Type": "ssh",
        "Code": null,
        "Ip": "fd7a:115c:a1e0:4b86:9046:80e:6c70:33b7",
        "UserAgent": "",
        "UserID": null,
        "SlugOrPort": "",
        "ConnectionID": "7a6fafdc-e3d0-43cb-a1b7-1f19802d7908",
        "DisconnectReason": "",
        "Time": "2025-07-10T10:14:38.942776145Z",
        "ConnectionStatus": "connected"
    }
}
```

Example of a [human readable](../../reference/cli/server/index.md#--log-human)
connection log entry, when `code-server` is opened:

```console
[API] 2025-07-03 06:57:16.157 [info]  coderd: connection_log  request_id=de3f6004-6cc1-4880-a296-d7c6ca1abf75  ID=f0249951-d454-48f6-9504-e73340fa07b7  Time="2025-07-03T06:57:16.144719Z"  OrganizationID=0665a54f-0b77-4a58-94aa-59646fa38a74  WorkspaceOwnerID=6dea5f8c-ecec-4cf0-a5bd-bc2c63af2efa  WorkspaceID=3c0b37c8-e58c-4980-b9a1-2732410480a5  WorkspaceName=dev  AgentName=main  Type=workspace_app  Code=200  Ip=127.0.0.1  UserAgent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36"  UserID=6dea5f8c-ecec-4cf0-a5bd-bc2c63af2efa  SlugOrPort=code-server  ConnectionID=<nil>  DisconnectReason=""  ConnectionStatus=connected
```

## Data Retention

Coder supports configurable retention policies that automatically purge old
Connection Logs. To enable automated purging, configure the
`--connection-logs-retention` flag or `CODER_CONNECTION_LOGS_RETENTION`
environment variable. For comprehensive configuration options, see
[Data Retention](../setup/data-retention.md).

## How to Enable Connection Logs

This feature is only available with a [Premium license](../../install/prepare/licensing.md).

---

# Notifications

Source: https://coder.com/docs/admin/monitoring/notifications

Notifications are sent by Coder in response to specific internal events, such as
a workspace being deleted or a user being created.

Available events may differ between versions.
For a list of all events, visit your Coder deployment's
`https://coder.example.com/deployment/notifications`.

## Event Types

Notifications are sent in response to internal events, to alert the affected
user(s) of the event.

Coder supports the following list of events:

### Template Events

These notifications are sent to users with **template admin** roles:

- Report: Workspace builds failed for template
  - This notification is delivered as part of a weekly cron job and summarizes
    the failed builds for a given template.
- Template deleted
- Template deprecated

### User Events

These notifications are sent to users with **owner** and **user admin** roles:

- User account activated
- User account created
- User account deleted
- User account suspended

These account notifications cover both user and service accounts.

These notifications are sent to users themselves:

- User account suspended
- User account activated
- User password reset (One-time passcode)

### Workspace Events

These notifications are sent to the workspace owner:

- Workspace automatic build failure
- Workspace autostop reminder
- Workspace created
- Workspace deleted
- Workspace manual build failure
- Workspace manually updated
- Workspace marked as dormant
- Workspace marked for deletion
- Out of memory (OOM) / Out of disk (OOD)
  - Template admins can [configure OOM/OOD](#configure-oomood-notifications) notifications in the template `main.tf`.
- Workspace automatically updated

## Delivery Methods

Notifications can be delivered through the Coder dashboard Inbox and by SMTP or webhook.
OOM/OOD notifications can be delivered to users in VS Code.

You can configure:

- SMTP or webhooks globally with
[`CODER_NOTIFICATIONS_METHOD`](../../../reference/cli/server/index.md#--notifications-method)
(default: `smtp`).
- Coder dashboard Inbox with
[`CODER_NOTIFICATIONS_INBOX_ENABLED`](../../../reference/cli/server/index.md#--notifications-inbox-enabled)
(default: `true`).

Premium customers can configure which method to use for each of the supported
[Events](#workspace-events).
See the [Preferences](#delivery-preferences) section for more details.

## Configuration

You can modify the notification delivery behavior in your Coder deployment's
`https://coder.example.com/settings/notifications`, or with the following server flags:

| Required | CLI                                 | Env                                     | Type       | Description                                                                                                           | Default |
|:--------:|-------------------------------------|-----------------------------------------|------------|-----------------------------------------------------------------------------------------------------------------------|---------|
|    ✔️    | `--notifications-dispatch-timeout`  | `CODER_NOTIFICATIONS_DISPATCH_TIMEOUT`  | `duration` | How long to wait while a notification is being sent before giving up.                                                 | 1m      |
|    ✔️    | `--notifications-method`            | `CODER_NOTIFICATIONS_METHOD`            | `string`   | Which delivery method to use (available options: 'smtp', 'webhook'). See [Delivery Methods](#delivery-methods) below. | smtp    |
|    -️    | `--notifications-max-send-attempts` | `CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS` | `int`      | The upper limit of attempts to send a notification.                                                                   | 5       |
|    -️    | `--notifications-inbox-enabled`     | `CODER_NOTIFICATIONS_INBOX_ENABLED`     | `bool`     | Enable or disable inbox notifications in the Coder dashboard.                                                         | true    |

### Configure OOM/OOD notifications

You can monitor out of memory (OOM) and out of disk (OOD) errors and alert users
when they overutilize memory and disk.

This can help prevent agent disconnects due to OOM/OOD issues.

To enable OOM/OOD notifications on a template, follow the steps in the
[resource monitoring guide](../../templates/extending-templates/resource-monitoring.md).

## SMTP (Email)

Use the `smtp` method to deliver notifications by email to your users. Coder
does not ship with an SMTP server, so you will need to configure Coder to use an
existing one.

**Server Settings:**

| Required | CLI                 | Env                     | Type     | Description                                                       | Default   |
|:--------:|---------------------|-------------------------|----------|-------------------------------------------------------------------|-----------|
|    ✔️    | `--email-from`      | `CODER_EMAIL_FROM`      | `string` | The sender's address to use (e.g. `"Coder <coder@example.com>"`). |           |
|    ✔️    | `--email-smarthost` | `CODER_EMAIL_SMARTHOST` | `string` | The SMTP relay to send messages (format: `hostname:port`)         |           |
|    ✔️    | `--email-hello`     | `CODER_EMAIL_HELLO`     | `string` | The hostname identifying the SMTP server.                         | localhost |

**Authentication Settings:**

| Required | CLI                          | Env                              | Type     | Description                                                               |
|:--------:|------------------------------|----------------------------------|----------|---------------------------------------------------------------------------|
|    -     | `--email-auth-username`      | `CODER_EMAIL_AUTH_USERNAME`      | `string` | Username to use with PLAIN/LOGIN authentication.                          |
|    -     | `--email-auth-password`      | `CODER_EMAIL_AUTH_PASSWORD`      | `string` | Password to use with PLAIN/LOGIN authentication.                          |
|    -     | `--email-auth-password-file` | `CODER_EMAIL_AUTH_PASSWORD_FILE` | `string` | File from which to load password for use with PLAIN/LOGIN authentication. |
|    -     | `--email-auth-identity`      | `CODER_EMAIL_AUTH_IDENTITY`      | `string` | Identity to use with PLAIN authentication.                                |

**TLS Settings:**

| Required | CLI                         | Env                           | Type     | Description                                                                                                                                                        | Default |
|:--------:|-----------------------------|-------------------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------|
|    -     | `--email-force-tls`         | `CODER_EMAIL_FORCE_TLS`       | `bool`   | Force a TLS connection to the configured SMTP smarthost. If port 465 is used, TLS will be forced. See <https://datatracker.ietf.org/doc/html/rfc8314#section-3.3>. | false   |
|    -     | `--email-tls-starttls`      | `CODER_EMAIL_TLS_STARTTLS`    | `bool`   | Enable STARTTLS to upgrade insecure SMTP connections using TLS. Ignored if `CODER_EMAIL_FORCE_TLS` is set.                                                         | false   |
|    -     | `--email-tls-skip-verify`   | `CODER_EMAIL_TLS_SKIPVERIFY`  | `bool`   | Skip verification of the target server's certificate (**insecure**).                                                                                               | false   |
|    -     | `--email-tls-server-name`   | `CODER_EMAIL_TLS_SERVERNAME`  | `string` | Server name to verify against the target certificate.                                                                                                              |         |
|    -     | `--email-tls-cert-file`     | `CODER_EMAIL_TLS_CERTFILE`    | `string` | Certificate file to use.                                                                                                                                           |         |
|    -     | `--email-tls-cert-key-file` | `CODER_EMAIL_TLS_CERTKEYFILE` | `string` | Certificate key file to use.                                                                                                                                       |         |

**NOTE:** you _MUST_ use `CODER_EMAIL_FORCE_TLS` if your smarthost supports TLS
on a port other than `465`.

### Send emails using G-Suite

After setting the required fields above:

1. Create an [App Password](https://myaccount.google.com/apppasswords) using the
   account you wish to send from.

1. Set the following configuration options:

   ```txt
   CODER_EMAIL_SMARTHOST=smtp.gmail.com:465
   CODER_EMAIL_AUTH_USERNAME=<user>@<domain>
   CODER_EMAIL_AUTH_PASSWORD="<app password created above (no spaces)>"
   ```

   **Note:** The `CODER_EMAIL_AUTH_PASSWORD` must be entered without spaces.

See
[this help article from Google](https://support.google.com/a/answer/176600?hl=en)
for more options.

### Send emails using Outlook.com

After setting the required fields above:

1. Set up an account on Microsoft 365 or outlook.com
1. Set the following configuration options:

   ```txt
   CODER_EMAIL_SMARTHOST=smtp-mail.outlook.com:587
   CODER_EMAIL_TLS_STARTTLS=true
   CODER_EMAIL_AUTH_USERNAME=<user>@<domain>
   CODER_EMAIL_AUTH_PASSWORD="<account password>"
   ```

See
[this help article from Microsoft](https://support.microsoft.com/en-us/office/pop-imap-and-smtp-settings-for-outlook-com-d088b986-291d-42b8-9564-9c414e2aa040)
for more options.

## Webhook

The webhook delivery method sends an HTTP POST request to the defined endpoint.
The purpose of webhook notifications is to enable integrations with other
systems.

**Settings**:

| Required | CLI                                | Env                                    | Type  | Description                             |
|:--------:|------------------------------------|----------------------------------------|-------|-----------------------------------------|
|    ✔️    | `--notifications-webhook-endpoint` | `CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT` | `url` | The endpoint to which to send webhooks. |

Here is an example payload for Coder's webhook notification:

```json
{
    "_version": "1.0",
    "msg_id": "88750cad-77d4-4663-8bc0-f46855f5019b",
    "payload": {
        "_version": "1.0",
        "notification_name": "Workspace Deleted",
        "user_id": "4ac34fcb-8155-44d5-8301-e3cd46e88b35",
        "user_email": "danny@coder.com",
        "user_name": "danny",
        "user_username": "danny",
        "actions": [
            {
                "label": "View workspaces",
                "url": "https://et23ntkhpueak.pit-1.try.coder.app/workspaces"
            },
            {
                "label": "View templates",
                "url": "https://et23ntkhpueak.pit-1.try.coder.app/templates"
            }
        ],
        "labels": {
            "initiator": "danny",
            "name": "my-workspace",
            "reason": "initiated by user"
        }
    },
    "title": "Workspace \"my-workspace\" deleted",
    "body": "Hi danny\n\nYour workspace my-workspace was deleted.\nThe specified reason was \"initiated by user (danny)\"."
}
```

The top-level object has these keys:

- `_version`: describes the version of this schema; follows semantic versioning
- `msg_id`: the UUID of the notification (matches the ID in the
  `notification_messages` table)
- `payload`: contains the specific details of the notification; described below
- `title`: the title of the notification message (equivalent to a subject in
  SMTP delivery)
- `body`: the body of the notification message (equivalent to the message body
  in SMTP delivery)

The `payload` object has these keys:

- `_version`: describes the version of this inner schema; follows semantic
  versioning
- `notification_name`: name of the event which triggered the notification
- `user_id`: Coder internal user identifier of the target user (UUID)
- `user_email`: email address of the target user
- `user_name`: name of the target user
- `user_username`: username of the target user
- `actions`: a list of CTAs (Call-To-Action); these are mainly relevant for SMTP
  delivery in which they're shown as buttons
- `labels`: dynamic map of zero or more string key-value pairs; these vary from
  event to event

## User Preferences

All users have the option to opt-out of any notifications. Go to **Account** ->
**Notifications** to turn notifications on or off. The delivery method for each
notification is indicated on the right hand side of this table.

![User Notification Preferences](../../../images/admin/monitoring/notifications/user-notification-preferences.png)

## Delivery Preferences

> [!NOTE]
> Delivery preferences is a Premium feature.
> [Learn more](https://coder.com/pricing#compare-plans).

Administrators can configure which delivery methods are used for each different
[event type](#event-types).

![preferences](../../../images/admin/monitoring/notifications/notification-admin-prefs.png)

You can find this page under
`https://$CODER_ACCESS_URL/deployment/notifications?tab=events`.

## Custom notifications

Custom notifications let you send an ad‑hoc notification to yourself using the Coder CLI.
These are useful for surfacing the result of long-running tasks or important state changes.
At this time, custom notifications can only be sent to the user making the request.

To send a custom notification, execute [`coder notifications custom <title> <message>`](../../../reference/cli/notifications/custom.md).

<!-- TODO(ssncferreira): Update when sending custom notifications to multiple users/roles is supported.
	 Explain deduplication behaviour for multiple users/roles.
	 See: https://github.com/coder/coder/issues/19768
-->
**Note:** The recipient is always the requesting user as targeting other users or groups isn’t supported yet.

### Examples

- Send yourself a quick update:

```sh
coder templates push -y && coder notifications custom "Template push complete" "Template version uploaded."
```

- Use in a script after a long-running task:

```sh
#!/usr/bin/env bash
set -o pipefail

if make test 2>&1 | tee test_output.log; then
  coder notifications custom "Tests Succeeded" $'Test results:\n  • ✅ success'
else
  failures=$(grep -Po '\d+(?=\s+failures)' test_output.log | tail -n1 || echo 0)
  coder notifications custom "Tests Failed" $'Test results:\n  • ❌ failed ('"$failures"' tests failed)'
  exit 1
fi
```

## Stop sending notifications

Administrators may wish to stop _all_ notifications across the deployment. We
support a killswitch in the CLI for these cases.

To pause sending notifications, execute
[`coder notifications pause`](../../../reference/cli/notifications/pause.md).

To resume sending notifications, execute
[`coder notifications resume`](../../../reference/cli/notifications/resume.md).

## Troubleshooting

If notifications are not being delivered, use the following methods to
troubleshoot:

1. Ensure notifications are being added to the `notification_messages` table.
1. Review any available error messages in the `status_reason` column
1. Review the logs. Search for the term `notifications` for diagnostic information.

   - If you do not see any relevant logs, set
    `CODER_LOG_FILTER=".*notifications.*"` to filter for notification-related logs.
1. If you are on version 2.15.x, notifications must be enabled using the
    `notifications`
    [experiment](../../../reference/feature-stages.md#early-access-features).

    Notifications are enabled by default in Coder v2.16.0 and later.

## Internals

The notification system is built to operate concurrently in a single- or
multi-replica Coder deployment, and has a built-in retry mechanism. It uses the
configured Postgres database to store notifications in a queue and facilitate
concurrency.

All messages are stored in the `notification_messages` table.

Messages older than seven days are deleted.

### Message States

![states](../../../images/admin/monitoring/notifications/notification-states.png)

_A notifier here refers to a Coder replica which is responsible for dispatching
the notification. All running replicas act as notifiers to process pending
messages._

- a message begins in `pending` state
- transitions to `leased` when a Coder replica acquires new messages from the
  database
  - new messages are checked for every `CODER_NOTIFICATIONS_FETCH_INTERVAL` (default: `15s`)
- if a message is delivered successfully, it transitions to `sent` state
- if a message encounters a non-retryable error (e.g. misconfiguration), it
  transitions to `permanent_failure`
- if a message encounters a retryable error (e.g. temporary server outage), it
  transitions to `temporary_failure`
  - this message will be retried up to `CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS`
    (default: 5)
  - this message will transition back to `pending` state after
    `CODER_NOTIFICATIONS_RETRY_INTERVAL` (default: 5m) and be retried
  - after `CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS` is exceeded, it transitions to
    `permanent_failure`

See [Troubleshooting](#troubleshooting) above for more details.

---

# Slack Notifications

Source: https://coder.com/docs/admin/monitoring/notifications/slack

[Slack](https://slack.com/) is a popular messaging platform designed for teams
and businesses, enabling real-time collaboration through channels, direct
messages, and integrations with external tools. With Coder's integration, you
can enable automated notifications directly within a self-hosted
[Slack app](https://api.slack.com/apps), keeping your team updated on key events
in your Coder environment.

Administrators can configure Coder to send notifications via an incoming webhook
endpoint. These notifications will be delivered as Slack messages direct to the
user. Routing is based on the user's email address, and this should be
consistent between Slack and their Coder login.

## Requirements

Before setting up Slack notifications, ensure that you have the following:

- Administrator access to the Slack platform to create apps
- Coder platform >=v2.16.0

## Create Slack Application

To integrate Slack with Coder, follow these steps to create a Slack application:

1. Go to the [Slack Apps](https://api.slack.com/apps) dashboard and create a new
   Slack App.

2. Under "Basic Information," you'll find a "Signing Secret." The Slack
   application uses it to
   [verify requests](https://api.slack.com/authentication/verifying-requests-from-slack)
   coming from Slack.

3. Under "OAuth & Permissions", add the following OAuth scopes:

   - `chat:write`: To send messages as the app.
   - `users:read`: To find the user details.
   - `users:read.email`: To find user emails.

4. Install the app to your workspace and note down the **Bot User OAuth Token**
   from the "OAuth & Permissions" section.

## Build a Webserver to Receive Webhooks

The Slack bot for Coder runs as a _Bolt application_, which is a framework
designed for building Slack apps using the Slack API.
[Bolt for JavaScript](https://github.com/slackapi/bolt-js) provides an
easy-to-use API for responding to events, commands, and interactions from Slack.

To build the server to receive webhooks and interact with Slack:

1. Initialize your project by running:

   ```sh
   npm init -y
   ```

2. Install the Bolt library:

   ```sh
   npm install @slack/bolt
   ```

3. Create and edit the `app.js` file. Below is an example of the basic
   structure:

   ```js
   const { App, LogLevel, ExpressReceiver } = require("@slack/bolt");
   const bodyParser = require("body-parser");

   const port = process.env.PORT || 6000;

   // Create a Bolt Receiver
   const receiver = new ExpressReceiver({
       signingSecret: process.env.SLACK_SIGNING_SECRET,
   });
   receiver.router.use(bodyParser.json());

   // Create the Bolt App, using the receiver
   const app = new App({
       token: process.env.SLACK_BOT_TOKEN,
       logLevel: LogLevel.DEBUG,
       receiver,
   });

   receiver.router.post("/v1/webhook", async (req, res) => {
       try {
           if (!req.body) {
               return res.status(400).send("Error: request body is missing");
           }

           const { title, body_markdown } = req.body;
              if (!title || !body_markdown) {
                  return res
                      .status(400)
                      .send('Error: missing fields: "title", or "body_markdown"');
           }

           const payload = req.body.payload;
           if (!payload) {
               return res.status(400).send('Error: missing "payload" field');
           }

           const { user_email, actions } = payload;
           if (!user_email || !actions) {
               return res
                   .status(400)
                   .send('Error: missing fields: "user_email", "actions"');
           }

           // Get the user ID using Slack API
           const userByEmail = await app.client.users.lookupByEmail({
               email: user_email,
           });

           const slackMessage = {
               channel: userByEmail.user.id,
               text: body_markdown,
               blocks: [
                   {
                       type: "header",
                       text: { type: "plain_text", text: title },
                   },
                   {
                       type: "section",
                       text: { type: "mrkdwn", text: body_markdown },
                   },
               ],
           };

           // Add action buttons if they exist
           if (actions && actions.length > 0) {
               slackMessage.blocks.push({
                   type: "actions",
                   elements: actions.map((action) => ({
                       type: "button",
                       text: { type: "plain_text", text: action.label },
                       url: action.url,
                   })),
               });
           }

           // Post message to the user on Slack
           await app.client.chat.postMessage(slackMessage);

           res.status(204).send();
       } catch (error) {
           console.error("Error sending message:", error);
           res.status(500).send();
       }
   });

   // Acknowledge clicks on link_button, otherwise Slack UI
   // complains about missing events.
   app.action("button_click", async ({ body, ack, say }) => {
       await ack(); // no specific action needed
   });

   // Start the Bolt app
   (async () => {
       await app.start(port);
       console.log("⚡️ Coder Slack bot is running!");
   })();
   ```

4. Set environment variables to identify the Slack app:

   ```sh
   export SLACK_BOT_TOKEN=xoxb-...
   export SLACK_SIGNING_SECRET=0da4b...
   ```

5. Start the web application by running:

   ```sh
   node app.js
   ```

## Enable Interactivity in Slack

Slack requires the bot to acknowledge when a user selects a URL action button.
This is handled by setting up interactivity.

Under "Interactivity & Shortcuts" in your Slack app settings, set the Request
URL to match the public URL of your web server's endpoint.

You can use any public endpoint that accepts and responds to POST requests with HTTP 200.
For temporary testing, you can set it to `https://httpbin.org/status/200`.

Once this is set, Slack will send interaction payloads to your server, which
must respond appropriately.

## Enable Webhook Integration in Coder

To enable webhook integration in Coder, define the POST webhook endpoint
matching the deployed Slack bot:

```sh
export CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT=http://localhost:6000/v1/webhook
```

Finally, go to the **Notification Settings** in Coder and switch the notifier to
**Webhook**.

---

# Microsoft Teams Notifications

Source: https://coder.com/docs/admin/monitoring/notifications/teams

[Microsoft Teams](https://www.microsoft.com/en-us/microsoft-teams) is a widely
used collaboration platform, and with Coder's integration, you can enable
automated notifications directly within Teams using workflows and
[Adaptive Cards](https://adaptivecards.io/)

Administrators can configure Coder to send notifications via an incoming webhook
endpoint. These notifications appear as messages in Teams chats, either with the
Flow Bot or a specified user/service account.

## Requirements

Before setting up Microsoft Teams notifications, ensure that you have the
following:

- Administrator access to the Teams platform
- Coder platform >=v2.16.0

## Build Teams Workflow

The process of setting up a Teams workflow consists of three key steps:

1. Configure the Webhook Trigger.

   Begin by configuring the trigger: **"When a Teams webhook request is
   received"**.

   Ensure the trigger access level is set to **"Anyone"**.

1. Setup the JSON Parsing Action.

   Add the **"Parse JSON"** action, linking the content to the **"Body"** of the
   received webhook request. Use the following schema to parse the notification
   payload:

   ```json
   {
       "type": "object",
       "properties": {
           "_version": {
               "type": "string"
           },
           "payload": {
               "type": "object",
               "properties": {
                   "_version": {
                       "type": "string"
                   },
                   "user_email": {
                       "type": "string"
                   },
                   "actions": {
                       "type": "array",
                       "items": {
                           "type": "object",
                           "properties": {
                               "label": {
                                   "type": "string"
                               },
                               "url": {
                                   "type": "string"
                               }
                           },
                           "required": ["label", "url"]
                       }
                   }
               }
           },
           "title_markdown": {
               "type": "string"
           },
           "body_markdown": {
               "type": "string"
           }
       }
   }
   ```

   This action parses the notification's title, body, and the recipient's email
   address.

1. Configure the Adaptive Card Action.

   Finally, set up the **"Post Adaptive Card in a chat or channel"** action with
   the following recommended settings:

   **Post as**: Flow Bot

   **Post in**: Chat with Flow Bot

   **Recipient**: `user_email`

   Use the following _Adaptive Card_ template:

   ```json
   {
       "$schema": "https://adaptivecards.io/schemas/adaptive-card.json",
       "type": "AdaptiveCard",
       "version": "1.0",
       "body": [
           {
               "type": "Image",
               "url": "https://coder.com/coder-logo-horizontal.png",
               "height": "40px",
               "altText": "Coder",
               "horizontalAlignment": "center"
           },
           {
               "type": "TextBlock",
               "text": "**@{replace(body('Parse_JSON')?['title_markdown'], '"', '\"')}**"
           },
           {
               "type": "TextBlock",
               "text": "@{replace(body('Parse_JSON')?['body_markdown'], '"', '\"')}",
               "wrap": true
           },
           {
               "type": "ActionSet",
               "actions": [@{replace(replace(join(body('Parse_JSON')?['payload']?['actions'], ','), '{', '{"type": "Action.OpenUrl",'), '"label"', '"title"')}]
           }
       ]
   }
   ```

   _Notice_: The Coder `actions` format differs from the `ActionSet` schema, so
   its properties need to be modified: include `Action.OpenUrl` type, rename
   `label` to `title`. Unfortunately, there is no straightforward solution for
   `for-each` pattern.

   Feel free to customize the payload to modify the logo, notification title, or
   body content to suit your needs.

## Enable Webhook Integration

To enable webhook integration in Coder, define the POST webhook endpoint created
by your Teams workflow:

```sh
export CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT=https://prod-16.eastus.logic.azure.com:443/workflows/f8fbe3e8211e4b638...`
```

Finally, go to the **Notification Settings** in Coder and switch the notifier to
**Webhook**.

## Limitations

1. **Public Webhook Trigger**: The Teams webhook trigger must be open to the
   public (**"Anyone"** can send the payload). It's recommended to keep the
   endpoint secret and apply additional authorization layers to protect against
   unauthorized access.

2. **Markdown Support in Adaptive Cards**: Note that Adaptive Cards support a
   [limited set of Markdown tags](https://learn.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-format?tabs=adaptive-md%2Cdesktop%2Cconnector-html).

---

# Security

Source: https://coder.com/docs/admin/security

<children></children>

For other security tips, visit our guide to
[security best practices](../../tutorials/best-practices/security-best-practices.md).

## Security Advisories

> [!CAUTION]
> If you discover a vulnerability in Coder, please do not hesitate to report it
> to us by following the [security policy](../../../SECURITY.md).

Security advisories are published on the
[GitHub Security Advisories](https://github.com/coder/coder/security/advisories)
page.

---

# Audit Logs

Source: https://coder.com/docs/admin/security/audit-logs

**Audit Logs** allows Auditors to monitor user operations in their deployment.

> [!NOTE]
> Audit logs require a
> [Premium license](https://coder.com/pricing#compare-plans).
> For more details, [contact your account team](https://coder.com/contact).

## Tracked Events

We track the following resources:

<!-- Code generated by 'make docs/admin/security/audit-logs.md'. DO NOT EDIT -->

| <b>Resource</b>                                                 |                                                                      |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
|-----------------------------------------------------------------|----------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| AIGatewayKey<br><i>create, delete</i>                           | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>hashed_secret</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_heartbeat_at</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>secret_prefix</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| AIProvider<br><i>create, write, delete</i>                      | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>base_url</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>enabled</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>settings</td><td>true</td></tr><tr><td>settings_key_id</td><td>false</td></tr><tr><td>type</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| AIProviderKey<br><i>create, delete</i>                          | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>api_key</td><td>true</td></tr><tr><td>api_key_key_id</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>provider_id</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| AISeatState<br><i>create</i>                                    | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>first_used_at</td><td>true</td></tr><tr><td>last_event_description</td><td>true</td></tr><tr><td>last_event_type</td><td>true</td></tr><tr><td>last_used_at</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_id</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| APIKey<br><i>login, logout, register, create, write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>allow_list</td><td>false</td></tr><tr><td>created_at</td><td>true</td></tr><tr><td>expires_at</td><td>true</td></tr><tr><td>hashed_secret</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>ip_address</td><td>false</td></tr><tr><td>last_used</td><td>true</td></tr><tr><td>lifetime_seconds</td><td>false</td></tr><tr><td>login_type</td><td>false</td></tr><tr><td>scopes</td><td>false</td></tr><tr><td>token_name</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_id</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| AuditOAuthConvertState<br><i></i>                               | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>true</td></tr><tr><td>expires_at</td><td>true</td></tr><tr><td>from_login_type</td><td>true</td></tr><tr><td>to_login_type</td><td>true</td></tr><tr><td>user_id</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| Group<br><i>create, write, delete</i>                           | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>avatar_url</td><td>true</td></tr><tr><td>chat_spend_limit_micros</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>members</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>quota_allowance</td><td>true</td></tr><tr><td>source</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| AuditableGroupAIBudget<br><i>write, delete</i>                  | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>group_id</td><td>false</td></tr><tr><td>group_name</td><td>false</td></tr><tr><td>spend_limit</td><td>true</td></tr><tr><td>spend_limit_micros</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| AuditableOrganizationMember<br><i></i>                          | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>roles</td><td>true</td></tr><tr><td>updated_at</td><td>true</td></tr><tr><td>user_id</td><td>true</td></tr><tr><td>username</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| AuditableUserAIBudgetOverride<br><i>write, delete</i>           | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>group_id</td><td>true</td></tr><tr><td>group_name</td><td>true</td></tr><tr><td>spend_limit</td><td>true</td></tr><tr><td>spend_limit_micros</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_id</td><td>false</td></tr><tr><td>username</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| Chat<br><i>create, write</i>                                    | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>agent_id</td><td>false</td></tr><tr><td>archived</td><td>true</td></tr><tr><td>build_id</td><td>false</td></tr><tr><td>client_type</td><td>false</td></tr><tr><td>compaction_requested_at</td><td>false</td></tr><tr><td>context_aggregate_hash</td><td>false</td></tr><tr><td>context_dirty_resources</td><td>false</td></tr><tr><td>context_dirty_since</td><td>false</td></tr><tr><td>context_error</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>dynamic_tools</td><td>false</td></tr><tr><td>generation_attempt</td><td>false</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>heartbeat_at</td><td>false</td></tr><tr><td>history_version</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>labels</td><td>true</td></tr><tr><td>last_error</td><td>false</td></tr><tr><td>last_model_config_id</td><td>false</td></tr><tr><td>last_read_message_id</td><td>false</td></tr><tr><td>last_reasoning_effort</td><td>false</td></tr><tr><td>last_turn_summary</td><td>false</td></tr><tr><td>mcp_server_ids</td><td>true</td></tr><tr><td>mode</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>owner_id</td><td>true</td></tr><tr><td>owner_name</td><td>false</td></tr><tr><td>owner_username</td><td>false</td></tr><tr><td>parent_chat_id</td><td>false</td></tr><tr><td>pin_order</td><td>true</td></tr><tr><td>plan_mode</td><td>false</td></tr><tr><td>queue_version</td><td>false</td></tr><tr><td>requires_action_deadline_at</td><td>false</td></tr><tr><td>retry_state</td><td>false</td></tr><tr><td>retry_state_version</td><td>false</td></tr><tr><td>root_chat_id</td><td>false</td></tr><tr><td>runner_id</td><td>false</td></tr><tr><td>snapshot_version</td><td>false</td></tr><tr><td>started_at</td><td>false</td></tr><tr><td>status</td><td>false</td></tr><tr><td>summary</td><td>false</td></tr><tr><td>summary_generated_at</td><td>false</td></tr><tr><td>title</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_acl</td><td>true</td></tr><tr><td>worker_id</td><td>false</td></tr><tr><td>workspace_id</td><td>true</td></tr></tbody></table> |
| ChatInstructionSettings<br><i>write</i>                         | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>id</td><td>false</td></tr><tr><td>include_default_system_prompt</td><td>true</td></tr><tr><td>include_default_system_prompt_set</td><td>true</td></tr><tr><td>name</td><td>false</td></tr><tr><td>plan_mode_instructions</td><td>true</td></tr><tr><td>system_prompt</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ChatModelConfig<br><i>create, write, delete</i>                 | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>ai_provider_id</td><td>true</td></tr><tr><td>compression_threshold</td><td>true</td></tr><tr><td>context_limit</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>deleted_at</td><td>false</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>enabled</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>is_default</td><td>true</td></tr><tr><td>model</td><td>true</td></tr><tr><td>options</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>updated_by</td><td>true</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ChatOperationalSettings<br><i>write</i>                         | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>chat_auto_archive_days</td><td>true</td></tr><tr><td>chat_debug_retention_days</td><td>true</td></tr><tr><td>chat_retention_days</td><td>true</td></tr><tr><td>computer_use_provider</td><td>true</td></tr><tr><td>debug_logging_allow_users</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>personal_model_overrides_enabled</td><td>true</td></tr><tr><td>workspace_ttl</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| CustomRole<br><i></i>                                           | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>is_system</td><td>false</td></tr><tr><td>member_permissions</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>org_permissions</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>site_permissions</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_permissions</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ExperimentRule<br><i>write</i>                                  | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>condition</td><td>true</td></tr><tr><td>experiment</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>mode</td><td>true</td></tr><tr><td>revision</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| GitSSHKey<br><i>create</i>                                      | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>private_key</td><td>true</td></tr><tr><td>private_key_key_id</td><td>false</td></tr><tr><td>public_key</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_id</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| GroupSyncSettings<br><i></i>                                    | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>auto_create_missing_groups</td><td>true</td></tr><tr><td>field</td><td>true</td></tr><tr><td>legacy_group_name_mapping</td><td>false</td></tr><tr><td>mapping</td><td>true</td></tr><tr><td>regex_filter</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| HealthSettings<br><i></i>                                       | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>dismissed_healthchecks</td><td>true</td></tr><tr><td>id</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| License<br><i>create, delete</i>                                | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>exp</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>jwt</td><td>false</td></tr><tr><td>uploaded_at</td><td>true</td></tr><tr><td>uuid</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| MCPServerConfig<br><i>create, write, delete</i>                 | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>allow_in_plan_mode</td><td>true</td></tr><tr><td>api_key_header</td><td>true</td></tr><tr><td>api_key_value</td><td>true</td></tr><tr><td>api_key_value_key_id</td><td>false</td></tr><tr><td>auth_type</td><td>true</td></tr><tr><td>availability</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>custom_headers</td><td>true</td></tr><tr><td>custom_headers_key_id</td><td>false</td></tr><tr><td>description</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>enabled</td><td>true</td></tr><tr><td>forward_coder_headers</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>icon_url</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>model_intent</td><td>true</td></tr><tr><td>oauth2_auth_url</td><td>true</td></tr><tr><td>oauth2_client_id</td><td>true</td></tr><tr><td>oauth2_client_secret</td><td>true</td></tr><tr><td>oauth2_client_secret_key_id</td><td>false</td></tr><tr><td>oauth2_revocation_url</td><td>true</td></tr><tr><td>oauth2_scopes</td><td>true</td></tr><tr><td>oauth2_token_url</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>signing_secret</td><td>true</td></tr><tr><td>signing_secret_key_id</td><td>false</td></tr><tr><td>slug</td><td>true</td></tr><tr><td>tool_allow_list</td><td>true</td></tr><tr><td>tool_deny_list</td><td>true</td></tr><tr><td>transport</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>updated_by</td><td>true</td></tr><tr><td>url</td><td>true</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| NotificationTemplate<br><i></i>                                 | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>actions</td><td>true</td></tr><tr><td>body_template</td><td>true</td></tr><tr><td>enabled_by_default</td><td>true</td></tr><tr><td>group</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>kind</td><td>true</td></tr><tr><td>method</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>title_template</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| NotificationsSettings<br><i></i>                                | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>id</td><td>false</td></tr><tr><td>notifier_paused</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| OAuth2ProviderApp<br><i></i>                                    | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>callback_url</td><td>true</td></tr><tr><td>client_id_issued_at</td><td>false</td></tr><tr><td>client_secret_expires_at</td><td>true</td></tr><tr><td>client_type</td><td>true</td></tr><tr><td>client_uri</td><td>true</td></tr><tr><td>contacts</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>dynamically_registered</td><td>true</td></tr><tr><td>grant_types</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>jwks</td><td>true</td></tr><tr><td>jwks_uri</td><td>true</td></tr><tr><td>logo_uri</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>policy_uri</td><td>true</td></tr><tr><td>redirect_uris</td><td>true</td></tr><tr><td>registration_access_token</td><td>true</td></tr><tr><td>registration_client_uri</td><td>true</td></tr><tr><td>response_types</td><td>true</td></tr><tr><td>scope</td><td>true</td></tr><tr><td>software_id</td><td>true</td></tr><tr><td>software_version</td><td>true</td></tr><tr><td>token_endpoint_auth_method</td><td>true</td></tr><tr><td>tos_uri</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| OAuth2ProviderAppSecret<br><i></i>                              | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>app_id</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>display_secret</td><td>false</td></tr><tr><td>hashed_secret</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>last_used_at</td><td>false</td></tr><tr><td>secret_prefix</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| OAuth2ProviderSettings<br><i></i>                               | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>dynamic_client_registration_enabled</td><td>true</td></tr><tr><td>id</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| Organization<br><i></i>                                         | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>default_org_member_roles</td><td>true</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>description</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>is_default</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>shareable_workspace_owners</td><td>true</td></tr><tr><td>updated_at</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| OrganizationSyncSettings<br><i></i>                             | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>assign_default</td><td>true</td></tr><tr><td>field</td><td>true</td></tr><tr><td>mapping</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| PrebuildsSettings<br><i></i>                                    | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>id</td><td>false</td></tr><tr><td>reconciliation_paused</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| RoleSyncSettings<br><i></i>                                     | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>field</td><td>true</td></tr><tr><td>mapping</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| Template<br><i>write, delete</i>                                | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>active_version_id</td><td>true</td></tr><tr><td>activity_bump</td><td>true</td></tr><tr><td>agents_allowed</td><td>true</td></tr><tr><td>allow_user_autostart</td><td>true</td></tr><tr><td>allow_user_autostop</td><td>true</td></tr><tr><td>allow_user_cancel_workspace_jobs</td><td>true</td></tr><tr><td>allow_workspace_renames</td><td>true</td></tr><tr><td>autostart_block_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_weeks</td><td>true</td></tr><tr><td>cors_behavior</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_name</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>default_ttl</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deprecated</td><td>true</td></tr><tr><td>description</td><td>true</td></tr><tr><td>disable_module_cache</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>failure_ttl</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>max_port_sharing_level</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_display_name</td><td>false</td></tr><tr><td>organization_icon</td><td>false</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>organization_name</td><td>false</td></tr><tr><td>provisioner</td><td>true</td></tr><tr><td>require_active_version</td><td>true</td></tr><tr><td>time_til_autostop_notify</td><td>true</td></tr><tr><td>time_til_dormant</td><td>true</td></tr><tr><td>time_til_dormant_autodelete</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>use_classic_parameter_flow</td><td>true</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table>                                                                                                                                                                                             |
| TemplateVersion<br><i>create, write</i>                         | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>archived</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_name</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>external_auth_providers</td><td>false</td></tr><tr><td>has_external_agent</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>message</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>readme</td><td>true</td></tr><tr><td>source_example_id</td><td>false</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| User<br><i>create, write, delete</i>                            | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>avatar_url</td><td>false</td></tr><tr><td>chat_spend_limit_micros</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>email</td><td>true</td></tr><tr><td>github_com_user_id</td><td>false</td></tr><tr><td>hashed_one_time_passcode</td><td>false</td></tr><tr><td>hashed_password</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>is_service_account</td><td>true</td></tr><tr><td>is_system</td><td>true</td></tr><tr><td>last_seen_at</td><td>false</td></tr><tr><td>login_type</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>one_time_passcode_expires_at</td><td>true</td></tr><tr><td>quiet_hours_schedule</td><td>true</td></tr><tr><td>rbac_roles</td><td>true</td></tr><tr><td>status</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>username</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| UserSecret<br><i>create, write, delete</i>                      | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>false</td></tr><tr><td>description</td><td>true</td></tr><tr><td>enabled</td><td>true</td></tr><tr><td>env_name</td><td>true</td></tr><tr><td>file_path</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_id</td><td>true</td></tr><tr><td>value</td><td>true</td></tr><tr><td>value_key_id</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| UserSkill<br><i>create, write, delete</i>                       | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>content</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>description</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_id</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| WorkspaceBuild<br><i>start, stop</i>                            | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>build_number</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>daily_cost</td><td>false</td></tr><tr><td>deadline</td><td>false</td></tr><tr><td>has_external_agent</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>initiator_by_avatar_url</td><td>false</td></tr><tr><td>initiator_by_name</td><td>false</td></tr><tr><td>initiator_by_username</td><td>false</td></tr><tr><td>initiator_id</td><td>false</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>max_deadline</td><td>false</td></tr><tr><td>notified_autostop_deadline</td><td>false</td></tr><tr><td>reason</td><td>false</td></tr><tr><td>template_version_id</td><td>true</td></tr><tr><td>template_version_preset_id</td><td>false</td></tr><tr><td>transition</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>workspace_id</td><td>false</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| WorkspaceProxy<br><i></i>                                       | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>created_at</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>derp_enabled</td><td>true</td></tr><tr><td>derp_only</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>region_id</td><td>true</td></tr><tr><td>token_hashed_secret</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>url</td><td>true</td></tr><tr><td>version</td><td>true</td></tr><tr><td>wildcard_hostname</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| WorkspaceTable<br><i></i>                                       | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody> | <tr><td>automatic_updates</td><td>true</td></tr><tr><td>autostart_schedule</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deleting_at</td><td>true</td></tr><tr><td>dormant_at</td><td>true</td></tr><tr><td>favorite</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_used_at</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>next_start_at</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>owner_id</td><td>true</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>ttl</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |

<!-- End generated by 'make docs/admin/security/audit-logs.md'. -->

## How to Filter Audit Logs

You can filter audit logs by the following parameters:

- `resource_type` - The type of the resource, such as a workspace, template,
  or user. For more resource types, refer to the
  [CoderSDK package documentation](https://pkg.go.dev/github.com/coder/coder/v2/codersdk#ResourceType).
- `resource_id` - The ID of the resource.
- `resource_target` - The name of the resource. Can be used instead of
  `resource_id`.
- `action`- The action applied to a resource, such as `create` or `delete`.
  For more actions, refer to the
  [CoderSDK package documentation](https://pkg.go.dev/github.com/coder/coder/v2/codersdk#AuditAction).
- `username` - The username of the user who triggered the action. You can also
  use `me` as a convenient alias for the logged-in user.
- `email` - The email of the user who triggered the action.
- `date_from` - The inclusive start date with format `YYYY-MM-DD`.
- `date_to` - The inclusive end date with format `YYYY-MM-DD`.
- `build_reason` - The reason for the workspace build, if `resource_type` is
  `workspace_build`. Refer to the
  [CoderSDK package documentation](https://pkg.go.dev/github.com/coder/coder/v2/codersdk#BuildReason)
  for a list of valid build reasons.

<a id="capturingexporting-audit-logs"></a>

## Capture and export audit logs

In addition to the Coder dashboard, there are multiple ways to consume or query
audit trails.

### REST API

You can retrieve audit logs via the Coder API.

Visit the
[`get-audit-logs` endpoint documentation](../../reference/api/audit.md#get-audit-logs)
for details.

### Service Logs

Audit trails are also dispatched as service logs and can be captured and
categorized using any log management tool such as [Splunk](https://splunk.com).

Example of a [JSON formatted](../../reference/cli/server/index.md#--log-json) audit
log entry:

```json
{
    "ts": "2023-06-13T03:45:37.294730279Z",
    "level": "INFO",
    "msg": "audit_log",
    "caller": "/home/coder/coder/enterprise/audit/backends/slog.go:38",
    "func": "github.com/coder/coder/v2/enterprise/audit/backends.(*SlogExporter).ExportStruct",
    "logger_names": ["coderd"],
    "fields": {
        "ID": "033a9ffa-b54d-4c10-8ec3-2aaf9e6d741a",
        "Time": "2023-06-13T03:45:37.288506Z",
        "UserID": "6c405053-27e3-484a-9ad7-bcb64e7bfde6",
        "OrganizationID": "00000000-0000-0000-0000-000000000000",
        "Ip": null,
        "UserAgent": null,
        "ResourceType": "workspace_build",
        "ResourceID": "ca5647e0-ef50-4202-a246-717e04447380",
        "ResourceTarget": "",
        "Action": "start",
        "Diff": {},
        "StatusCode": 200,
        "AdditionalFields": {
            "workspace_name": "linux-container",
            "build_number": "9",
            "build_reason": "initiator",
            "workspace_owner": ""
        },
        "RequestID": "bb791ac3-f6ee-4da8-8ec2-f54e87013e93",
        "ResourceIcon": ""
    }
}
```

Example of a [human readable](../../reference/cli/server/index.md#--log-human) audit
log entry:

```console
2023-06-13 03:43:29.233 [info]  coderd: audit_log  ID=95f7c392-da3e-480c-a579-8909f145fbe2  Time="2023-06-13T03:43:29.230422Z"  UserID=6c405053-27e3-484a-9ad7-bcb64e7bfde6  OrganizationID=00000000-0000-0000-0000-000000000000  Ip=<nil>  UserAgent=<nil>  ResourceType=workspace_build  ResourceID=988ae133-5b73-41e3-a55e-e1e9d3ef0b66  ResourceTarget=""  Action=start  Diff="{}"  StatusCode=200  AdditionalFields="{\"workspace_name\":\"linux-container\",\"build_number\":\"7\",\"build_reason\":\"initiator\",\"workspace_owner\":\"\"}"  RequestID=9682b1b5-7b9f-4bf2-9a39-9463f8e41cd6  ResourceIcon=""
```

<a id="purging-old-audit-logs"></a>

## Purge old audit logs

> [!WARNING]
> Audit Logs provide critical security and compliance information. Purging Audit Logs may impact your organization's ability
> to investigate security incidents or meet compliance requirements. Consult your security and compliance teams before purging any audit data.

### Data Retention

Coder supports configurable retention policies that automatically purge old
Audit Logs. To enable automated purging, configure the
`--audit-logs-retention` flag or `CODER_AUDIT_LOGS_RETENTION` environment
variable. For comprehensive configuration options, see
[Data Retention](../setup/data-retention.md).

### Manual Purging

Alternatively, you can purge Audit Logs manually by running SQL queries
directly against the database.

Audit Logs can account for a large amount of disk usage. Use the following
query to determine the amount of disk space used by the `audit_logs` table.

```sql
SELECT
    relname AS table_name,
    pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
    pg_size_pretty(pg_relation_size(relid)) AS table_size,
    pg_size_pretty(pg_indexes_size(relid)) AS indexes_size,
    (SELECT COUNT(*) FROM audit_logs) AS total_records
FROM pg_catalog.pg_statio_user_tables
WHERE relname = 'audit_logs'
ORDER BY pg_total_relation_size(relid) DESC;
```

Should you wish to purge these records, it is safe to do so. This can only be done by running SQL queries
directly against the `audit_logs` table in the database. We advise users to only purge old records (>1yr)
and in accordance with your compliance requirements.

### Maintenance Procedures for the Audit Logs Table

> [!NOTE]
> `VACUUM FULL` acquires an exclusive lock on the table, blocking all reads and writes. For more information, see the [PostgreSQL VACUUM documentation](https://www.postgresql.org/docs/current/sql-vacuum.html).

You may choose to run a `VACUUM` or `VACUUM FULL` operation on the audit logs table to reclaim disk space. If you choose to run the `FULL` operation, consider the following when doing so:

- **Run during a planned maintenance window** to ensure ample time for the operation to complete and minimize impact to users
- **Stop all running instances of `coderd`** to prevent connection errors while the table is locked. The actual steps for this will depend on your particular deployment setup. For example, if your `coderd` deployment is running on Kubernetes:

  ```sh
  kubectl scale deployment coder --replicas=0 -n coder
  ```

- **Terminate lingering connections** before running the `VACUUM` operation to ensure it starts immediately

  ```sql
  SELECT pg_terminate_backend(pg_stat_activity.pid)
  FROM pg_stat_activity
  WHERE pg_stat_activity.datname = 'coder' AND pid <> pg_backend_pid();
  ```

- **Only `coderd` needs to scale down** - external provisioner daemons, workspace proxies, and workspace agents don't connect to the database directly.

After the vacuum completes, scale coderd back up:

```sh
kubectl scale deployment coder --replicas= -n coder
```

### Backup/Archive

Consider exporting or archiving these records before deletion:

```sql
-- Export to CSV
COPY (SELECT * FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year')
TO '/path/to/audit_logs_archive.csv' DELIMITER ',' CSV HEADER;

-- Copy to archive table
CREATE TABLE audit_logs_archive AS
SELECT * FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year';
```

### Permanent Deletion

> [!NOTE]
> For large `audit_logs` tables, consider running the `DELETE` operation during maintenance windows as it may impact
> database performance. You can also batch the deletions to reduce lock time.

```sql
DELETE FROM audit_logs WHERE time < CURRENT_TIMESTAMP - INTERVAL '1 year';
-- Consider running `VACUUM VERBOSE audit_logs` afterwards for large datasets to reclaim disk space.
```

## How to Enable Audit Logs

This feature is only available with a [Premium license](../../install/prepare/licensing.md), and is automatically enabled.

---

# Secrets

Source: https://coder.com/docs/admin/security/secrets

Coder is open-minded about how you get your secrets into your workspaces. For
more information about how to use secrets and other security tips, visit our
guide to
[security best practices](../../tutorials/best-practices/security-best-practices.md#secrets).

Use this guide to configure how templates make secrets available to Coder
workspaces. To authenticate workspace provisioners with Coder, see the
<a href="../../install/operate/provisioners/index.md#authentication">provisioners documentation</a>.
For secret values that developers manage themselves, see
[User secrets](../../user-guides/user-secrets.md).

## Before you begin

Your first attempt to use secrets with Coder should be your local method. You
can do everything you can locally and more with your Coder workspace, so
whatever workflow and tools you already use to manage secrets may be brought
over.

Often, this workflow is simply:

1. Give your users their secrets in advance
1. Your users write them to a persistent file after they've built their
   workspace

[Template parameters](../templates/extending-templates/parameters.md) are a
dangerous way to accept secrets. We show parameters in cleartext around the
product. Assume anyone with view access to a workspace can also see its
parameters.

## SSH Keys

Coder generates SSH key pairs for each user. This can be used as an
authentication mechanism for git providers or other tools. Within workspaces,
git will attempt to use this key within workspaces via the `$GIT_SSH_COMMAND`
environment variable.

Users can view their public key in their account settings:

![SSH keys in account settings](../../images/ssh-keys.png)

> [!NOTE]
> SSH keys are never stored in Coder workspaces, and are fetched only when
> SSH is invoked. The keys are held in-memory and never written to disk.

## User secrets

User secrets are developer-managed values that Coder injects at workspace start.
If a user secret targets the same environment variable name or file path as a
template-provided variable or file, Coder injects the user secret into that
workspace. A secret can be disabled, in which case it is stored but not injected
until it is re-enabled. User secret values are covered by
[Database Encryption](./database-encryption.md) when it is enabled. See the
[User secrets guide](../../user-guides/user-secrets.md).

## Dynamic Secrets

Dynamic secrets are attached to the workspace lifecycle and automatically
injected into the workspace. With a little bit of up front template work, they
make life simpler for both the end user and the security team.

This method is limited to
[services with Terraform providers](https://registry.terraform.io/browse/providers),
which excludes obscure API providers.

Dynamic secrets can be implemented in your template code like so:

```tf
resource "twilio_iam_api_key" "api_key" {
  account_sid   = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  friendly_name = "Test API Key"
}

resource "coder_agent" "main" {
  # ...
  env = {
    # Let users access the secret via $TWILIO_API_SECRET
    TWILIO_API_SECRET = "${twilio_iam_api_key.api_key.secret}"
  }
}
```

A catch-all variation of this approach is dynamically provisioning a cloud
service account (e.g
[GCP](https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/google_service_account_key#private_key))
for each workspace and then making the relevant secrets available via the
cloud's secret management system.

<a id="displaying-secrets"></a>

## Display secrets

While you can inject secrets into the workspace via environment variables, you
can also show them in the Workspace UI with
[`coder_metadata`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/metadata).

![Secrets UI](../../images/admin/secret-metadata.PNG)

Can be produced with

```tf
resource "twilio_iam_api_key" "api_key" {
  account_sid   = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  friendly_name = "Test API Key"
}


resource "coder_metadata" "twilio_key" {
  resource_id = twilio_iam_api_key.api_key.id
  item {
    key   = "Username"
    value = "Administrator"
  }
  item {
    key       = "Password"
    value     = twilio_iam_api_key.api_key.secret
    sensitive = true
  }
}
```

## Secrets Management

For more advanced secrets management, you can use a secrets management tool to
store and retrieve secrets in your workspace. For example, you can use
[HashiCorp Vault](https://www.vaultproject.io/) to inject secrets into your
workspace.

Refer to our [HashiCorp Vault Integration](../integrations/vault.md) guide for
more information on how to integrate HashiCorp Vault with Coder.

## Next steps

- [Security - best practices](../../tutorials/best-practices/security-best-practices.md)

---

# Database Encryption

Source: https://coder.com/docs/admin/security/database-encryption

By default, Coder stores external user tokens and other sensitive values in
plaintext in the database. Database Encryption allows Coder administrators to
encrypt these values at-rest, preventing attackers with database access from
reading or misusing them.

## How it works

Coder allows administrators to specify
[external token encryption keys](../../reference/cli/server/index.md#--external-token-encryption-keys).
If configured, Coder will use these keys to encrypt external user tokens before
storing them in the database. The encryption algorithm used is AES-256-GCM with
a 32-byte key length.

Coder will use the first key provided for both encryption and decryption. If
additional keys are provided, Coder will use it for decryption only. This allows
administrators to rotate encryption keys without invalidating existing tokens.

The following database fields are currently encrypted:

- `user_links.oauth_access_token`
- `user_links.oauth_refresh_token`
- `external_auth_links.oauth_access_token`
- `external_auth_links.oauth_refresh_token`
- `crypto_keys.secret`
- `user_secrets.value`
- `gitsshkeys.private_key`
- `chat_mcp_servers.headers`

Additional database fields may be encrypted in the future.

### Implementation notes

Each encrypted database column `$C` has a corresponding
`$C_key_id` column. This column is used to determine which encryption key was
used to encrypt the data. This allows Coder to rotate encryption keys without
invalidating existing tokens, and provides referential integrity for encrypted
data.

The `$C_key_id` column stores the first 7 bytes of the SHA-256 hash of the
encryption key used to encrypt the data.

Encryption keys in use are stored in `dbcrypt_keys`. This table stores a
record of all encryption keys that have been used to encrypt data. Active keys
have a null `revoked_key_id` column, and revoked keys have a non-null
`revoked_key_id` column. You cannot revoke a key until you have rotated all
values using that key to a new key.

<a id="enabling-encryption"></a>

## Turn on encryption

> [!NOTE]
> Enabling encryption does not encrypt all existing data. To encrypt
> existing data, see [rotating keys](#rotate-keys) below.

- Ensure you have a valid backup of your database. **Do not skip this step.** If
  you are using the built-in PostgreSQL database, you can run
  [`coder server postgres-builtin-url`](../../reference/cli/server/postgres-builtin-url.md)
  to get the connection URL.

- Generate a 32-byte random key and base64-encode it. For example:

```sh
dd if=/dev/urandom bs=32 count=1 | base64
```

- Store this key in a secure location (for example, a Kubernetes secret):

```sh
kubectl create secret generic coder-external-token-encryption-keys --from-literal=keys=<key>
```

- In your Coder configuration set `CODER_EXTERNAL_TOKEN_ENCRYPTION_KEYS` to a
  comma-separated list of base64-encoded keys. For example, in your Helm
  `values.yaml`:

```yaml
coder:
  env:
    [...]
    - name: CODER_EXTERNAL_TOKEN_ENCRYPTION_KEYS
      valueFrom:
        secretKeyRef:
          name: coder-external-token-encryption-keys
          key: keys
```

- Restart the control plane. It will now encrypt all new data with the provided
  key.

<a id="rotating-keys"></a>

## Rotate keys

We recommend only having one active encryption key at a time normally. However,
if you need to rotate keys, you can perform the following procedure:

- Ensure you have a valid backup of your database. **Do not skip this step.**

- Generate a new encryption key following the same procedure as above.

- Add the above key to the list of
  [external token encryption keys](../../reference/cli/server/index.md#--external-token-encryption-keys).
  **The new key must appear first in the list**. For example, in the Kubernetes
  secret created above:

```yaml
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: coder-external-token-encryption-keys
  namespace: coder-namespace
data:
  keys: <new-key>,<old-key1>,<old-key2>,...
```

- After updating the configuration, restart the control plane. It will now
  encrypt all new data with the new key, but will be able to decrypt tokens
  encrypted with the old key(s).

- To re-encrypt all encrypted database fields with the new key, run
  [`coder server dbcrypt rotate`](../../reference/cli/server/dbcrypt/rotate.md).
  This command will re-encrypt all tokens with the specified new encryption key.
  We recommend performing this action during a maintenance window.

  This command requires direct access to the database.
  If you are using the built-in PostgreSQL database, you can run
  [`coder server postgres-builtin-url`](../../reference/cli/server/postgres-builtin-url.md)
  to get the connection URL.

- Once the above command completes successfully, remove the old encryption key
  from Coder's configuration and restart Coder once more. You can now safely
  delete the old key from your secret store.

<a id="disabling-encryption"></a>

## Turn off encryption

To disable encryption, perform the following actions:

- Ensure you have a valid backup of your database. **Do not skip this step.**

- Stop all active `coderd` instances. This will prevent new encrypted data from
  being written, which may cause the next step to fail.

- Run
  [`coder server dbcrypt decrypt`](../../reference/cli/server/dbcrypt/decrypt.md).
  This command will decrypt all encrypted user tokens and revoke all active
  encryption keys.

  > [!NOTE]
  > for `decrypt` command, the equivalent environment variable for
  > `--keys` is `CODER_EXTERNAL_TOKEN_ENCRYPTION_DECRYPT_KEYS` and not
  > `CODER_EXTERNAL_TOKEN_ENCRYPTION_KEYS`. This is explicitly named differently
  > to help prevent accidentally decrypting data.

- Remove all
  [external token encryption keys](../../reference/cli/server/index.md#--external-token-encryption-keys)
  from Coder's configuration.

- Start `coderd`. You can now safely delete the encryption keys from your secret
  store.

<a id="deleting-encrypted-data"></a>

## Delete encrypted data

> [!CAUTION]
> This is a destructive operation.

To delete all encrypted data from your database, perform the following actions:

- Ensure you have a valid backup of your database. **Do not skip this step.**

- Stop all active `coderd` instances. This will prevent new encrypted data from
  being written.

- Run
  [`coder server dbcrypt delete`](../../reference/cli/server/dbcrypt/delete.md).
  This command will delete all encrypted user tokens and revoke all active
  encryption keys.

- Remove all
  [external token encryption keys](../../reference/cli/server/index.md#--external-token-encryption-keys)
  from Coder's configuration.

- Start `coderd`. You can now safely delete the encryption keys from your secret
  store.

## Troubleshooting

- If Coder detects that the data stored in the database was not encrypted with
  any known keys, it will refuse to start. If you are seeing this behavior,
  ensure that the encryption keys provided are correct.
- If Coder detects that the data stored in the database was encrypted with a key
  that is no longer active, it will refuse to start. If you are seeing this
  behavior, ensure that the encryption keys provided are correct and that you
  have not revoked any keys that are still in use.
- Decryption may fail if newly encrypted data is written while decryption is in
  progress. If this happens, ensure that all active coder instances are stopped,
  and retry.

## Next steps

- [Security - best practices](../../tutorials/best-practices/security-best-practices.md)

---

# Run AI Coding Agents in Coder

Source: https://coder.com/docs/ai-coder

Learn how to run & manage coding agents with Coder, both alongside existing workspaces and for background task execution.

Coder supports several ways to run and [govern](#govern-ai-activity-with-ai-governance) coding agents, depending on how much control you need over execution and orchestration:

- [Coder Agents](#coder-agents), self-hosted AI workflow infrastructure best suited for headless, automated background tasks and parallel agentic development in a conversational UI.
- [Agent Relay](#agent-relay), best suited for preserving the cloud agent experience developers already know while running execution in self-hosted Coder workspaces.
- [Agents in the IDE](#agents-in-the-ide), best suited for in-editor code assist use cases alongside a developer's existing workflow.
- [Agents in workspace templates](#agents-in-workspace-templates), best suited for developers who want to pair one-on-one with an agent like Claude Code or Codex in a workspace.

## Coder Agents

In cases where the IDE is secondary, such as prototyping, research, or long-running background jobs, [Coder Agents](./agents/index.md) is the recommended way to delegate development work to coding agents in your Coder deployment.

Coder Agents is a native AI coding agent built into Coder.
The agent loop runs in the Coder control plane on your infrastructure rather than inside the workspace, so workspaces can be completely network isolated.
Developers interact with agents through the web UI or the REST API.

![Coder Agents chat interface with git diff sidebar](../images/agents-hero-image.png)

[Learn more about Coder Agents](./agents/index.md) for architecture details, supported LLM providers, and how to get started.

## Agent Relay

[Agent Relay](./agent-relay/index.md) connects a supported cloud-hosted AI agent provider's hosted sessions to self-hosted Coder workspaces.
The provider's orchestration and AI inference stay cloud-hosted; a worker process inside the workspace executes the agent's tool calls.
[Cursor Cloud Agents](https://cursor.com/cloud) and [Claude Code](https://claude.ai/code) are the supported providers.

Agent Relay is in [early access](../reference/feature-stages.md#early-access-features) and is in closed preview with select customers.

[Learn more about Agent Relay](./agent-relay/index.md) for architecture details and supported providers.

## Agents in the IDE

Coder [integrates with IDEs](../user-guides/workspace-access/index.md) such as Cursor, Devin Desktop, and Zed that include built-in coding agents to work alongside developers.
Additionally, template admins can [pre-install extensions](https://registry.coder.com/modules/coder/vscode-web) for agents such as GitHub Copilot.

These agents work well inside existing Coder workspaces as they can simply be enabled via an extension or are built-into the editor.

## Agents in workspace templates

Template admins can install terminal-based coding agents, such as Claude Code or Codex, directly into a workspace template using a [registry module](https://registry.coder.com).
Pick from a curated list of agent modules in the [template builder](../admin/templates/creating-templates.md#template-builder), or add a module directly in Terraform:

```tf
module "claude-code" {
  source   = "registry.coder.com/coder/claude-code/coder"
  version  = "~> 5.2"
  agent_id = coder_agent.main.id
}
```

Visit the [Coder Registry](https://registry.coder.com) for the full list of available agent modules.

[Learn more about extending templates](../admin/templates/extending-templates/index.md).

## Govern AI activity with AI Governance

AI coding tools are quickly becoming core to how engineering teams ship software.
As adoption grows, platform teams want a clear picture of how AI is being used, consistent guardrails across teams, and predictable cost controls so they can confidently scale AI tooling to the whole organization.

[AI Governance](./ai-governance.md) is included with a Premium license and adds observability, management, and policy controls for AI tooling across your Coder deployment.
It includes:

- [AI Gateway](./ai-gateway/index.md) for centralized authentication, audit trails of prompts and tool invocations, and policy enforcement against upstream LLM providers.
- [Agent Firewall](./agent-firewall/index.md) for process-level network and command policies that restrict what agents can reach and do inside a workspace.

[Learn more about AI Governance](./ai-governance.md) for use cases, entitlements, and how to enable it in your deployment.

---

# Best Practices

Source: https://coder.com/docs/ai-coder/best-practices

This document includes a mix of cultural and technical best practices and guidelines for introducing AI agents into your organization.

## Identify Use Cases

To successfully implement AI coding agents, identify 3-5 practical use cases where AI tools can deliver real value. Additionally, find a target group of developers and projects that are the best candidates for each specific use case.

Below are common scenarios where AI coding agents provide the most impact, along with the right tools for each use case:

| Scenario                                       | Description                                                                                                               | Examples                                                                                                             | Tools                                                                                                        |
|------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
| **Automating actions in the IDE**              | Supplement tedious development with agents                                                                                | Small refactors, generating unit tests, writing inline documentation, code search and navigation                     | [IDE Agents](./ide-agents.md) in Workspaces                                                                  |
| **Developer-led investigation and setup**      | Developers delegate research and initial implementation to AI, then take over in their preferred IDE to complete the work | Bug triage and analysis, exploring technical approaches, understanding legacy code, creating starter implementations | [Coder Agents](./agents/index.md), to a full IDE with [Workspaces](../user-guides/workspace-access/index.md) |
| **Prototyping & Business Applications**        | User-friendly interface for engineers and non-technical users to build and prototype within new or existing codebases     | Creating dashboards, building simple web apps, data analysis workflows, proof-of-concept development                 | [Coder Agents](./agents/index.md)                                                                            |
| **Full background jobs & long-running agents** | Agents that run independently without user interaction for extended periods of time                                       | Automated code reviews, scheduled data processing, continuous integration tasks, monitoring and alerting             | [Coder Agents API](../reference/api/chats.md)                                                                |
| **External agents and chat clients**           | External AI agents and chat clients that need access to Coder workspaces for development environments and code sandboxing | ChatGPT, Claude Desktop, custom enterprise agents running tests, performing development tasks, code analysis         | [MCP Server](./mcp-server.md)                                                                                |

## Provide Agents with Proper Context

While LLMs are trained on general knowledge, it's important to provide additional context to help agents understand your codebase and organization.

For [Coder Agents](./agents/index.md), context comes from a few complementary places. Platform admins configure a [system prompt](./agents/platform-controls/index.md) that applies to every chat and register [MCP servers](./agents/platform-controls/mcp-servers.md) per organization. Repos and workspace templates can ship reusable [skills](./agents/extending-agents.md) under `.agents/skills/`, which the agent discovers automatically when it attaches to the workspace. Developers don't need to manage memory files or wire up tools themselves.

The rest of this section covers patterns for agents you run yourself inside a workspace, such as Claude Code or Codex.

### Memory

Coding Agents like Claude Code often refer to a [memory file](https://docs.anthropic.com/en/docs/claude-code/memory) in order to gain context about your repository or organization.

Look up the docs for the specific agent you're using to learn more about how to provide context to your agents.

### Tools (Model Context Protocol)

Agents can also use tools, often via [Model Context Protocol](https://modelcontextprotocol.io/introduction) to look up information or perform actions. A common example would be fetching style guidelines from an internal wiki, or looking up the documentation for a service within your catalog.

Look up the docs for the specific agent you're using to learn more about how to provide tools to your agents.

#### Our Favorite MCP Servers

In internal testing, we have seen significant improvements in agent performance when these tools are added via MCP.

- [Playwright](https://github.com/microsoft/playwright-mcp): Instruct your agent
  to open a browser, and check its work by viewing output and taking
  screenshots.
- [desktop-commander](https://github.com/wonderwhy-er/DesktopCommanderMCP):
  Instruct your agent to run long-running tasks (e.g. `npm run dev`) in the background instead of blocking the main thread.

## Security & Permissions

LLMs and agents can be dangerous if not run with proper boundaries. Be sure not to give agents full permissions on behalf of a user, and instead use separate identities with limited scope whenever interacting autonomously.

[Learn more about the Agent Firewall](./agent-firewall/index.md)

## Keep it Simple

Today's LLMs and AI agents are not going to refactor entire codebases with production-grade code on their own! Using coding agents can be extremely fun and productive, but it is important to keep the scope of your use cases small and simple, and grow them over time.

---

# In the IDE

Source: https://coder.com/docs/ai-coder/ide-agents

Learn how to use Coder Workspaces with IDEs and plugins to run coding agents like Cursor, GitHub Copilot, Devin Desktop, RooCode, and more.

## How it works

Coder Workspaces are full development environments that run on your cloud infrastructure, such as Kubernetes or AWS EC2. Developers can connect with their favorite IDEs with pre-configured extensions and configuration for agentic coding.

![Workspace Page](../images/guides/ai-agents/workspace-page.png)

## Coder versus Local Development

Running coding agents in Coder workspaces provides several advantages over running them locally:

- **Fast, out-of-the-box setup**: LLMs, proxies, and MCP tools can be pre-configured for developers to use immediately, eliminating setup time and configuration hassles.
- **Consistent environments**: All developers use the same standardized environments, ensuring consistent access to tools and resources.
- **Resource optimization**: Leverage powerful cloud resources without taxing local machines.
- **Security and isolation**: Keep sensitive code, API keys, and secrets in controlled environments.

[Learn more about Coder](https://coder.com/cde/compare)

## IDE Support

Follow the Coder Documentation for [Connecting to Workspaces](../user-guides/workspace-access/index.md) to connect to your Coder Workspaces with your favorite IDEs.

## Pre-Configuring Extensions &amp; Plugins

Read our [VS Code module documentation](https://registry.coder.com/modules/coder/vscode-web) for examples on how to pre-install plugins like GitHub Copilot, RooCode, Sourcegraph Cody, and more in Coder workspaces.

---

# Coder Agents

Source: https://coder.com/docs/ai-coder/agents

Coder Agents is a chat interface and API for delegating development work and research to coding agents in your Coder deployment. Developers describe the work they want done, and Coder Agents handles selecting a template, provisioning a workspace, and executing the task.

Coder Agents includes its own self-hosted AI coding
agent that runs the agent loop directly within the Coder control plane.

No specialized software, API keys, or network access is required inside your workspace. The only requirement is network access between the control plane and external LLM providers.

<video autoplay playsinline loop>
  <source src="https://raw.githubusercontent.com/coder/coder/refs/heads/main/docs/images/guides/ai-agents/coder-agents-ui.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>

## What Coder Agents is and isn't

It is a standalone agent written in Go.
It implements standard agentic patterns, such as sub-agent delegation, context compaction, file editing, and shell execution.
It works with any LLM provider you configure.

It is not a wrapper around third-party agent tools like Claude Code
or Codex.

Coder Agents is not a replacement for your text editor or IDE. It is the
primary interface where developers work with and orchestrate coding agents.
Developers still connect to workspaces via VS Code, Cursor, JetBrains, or any
other editor to review, refine, and complete work that the agent produces.

## Who Coder Agents is for

Coder Agents is designed for organizations that need to self-host their AI
coding workflows and maintain full control over how agents operate. It is a
strong fit for:

- **Regulated industries** such as financial services, healthcare, and
  government, where AI tools must run on controlled infrastructure with
  auditable access and strict network boundaries.
- **Platform engineering teams** that want to provide developers with a
  high-quality AI coding experience without managing per-workspace agent
  installations, API key distribution, or third-party agent licensing.
- **Organizations with existing Coder deployments** that want to add agentic
  capabilities using their current templates, workspaces, and identity
  providers rather than adopting a separate SaaS product.

Coder Agents runs entirely self-hosted. There is no SaaS or managed component — the agent
loop, chat history, and all tool execution happen within your Coder deployment.

## How it works

The agent loop runs inside [the control plane](./architecture.md). When a user
submits a prompt, the control plane:

1. Sends the prompt to the configured LLM provider (Anthropic, OpenAI, Google,
   Azure, AWS Bedrock, or any OpenAI-compatible endpoint).
1. Receives the model's response, which may include tool calls such as reading
   files, writing code, or running shell commands.
1. Executes tool calls by connecting to a Coder workspace over the existing
   workspace connection — the same path used for web terminals, port
   forwarding, and IDE access.
1. Returns tool results to the model and continues the loop until the task is
   complete.

The workspace itself has no knowledge of AI. It is standard compute
infrastructure — there are no LLM API keys, no agent harnesses, and no special
software installed. All intelligence lives in the control plane.

<img src="../../images/guides/ai-agents/agent-loop.png" alt="Architecture diagram showing the control plane in the center, with arrows out to LLM providers and arrows to workspaces">

<small>The agent loop runs in the control plane. It makes outbound requests to LLM
providers and connects to workspaces only when tool execution is needed.</small>

### Automatic workspace provisioning

Not every chat requires a workspace.
The agent uses the conversation and available tools when they're sufficient for your request.
If missing tools, skills, MCP integrations, or context block progress, the agent creates a suitable workspace and uses its capabilities to continue.
Workspaces also support reading code, running commands, and editing files.
Requests to fix a bug or build an app authorize the necessary workspace setup; you don't need to ask for a workspace separately.
Questions and self-contained code examples don't need a workspace when the conversation and available tools are sufficient.

This means:

- **Faster responses** — conversations that don't require workspace access
  start immediately with no provisioning delay.
- **Lower infrastructure cost**: the agent uses existing tools and context when they can complete your request without a workspace.

When a workspace _is_ needed, the agent reads the templates available to that user —
including their descriptions and parameters — selects the appropriate one, and
creates a workspace automatically. Template visibility is scoped to the user's role and permissions, so the agent can only select templates the user is authorized to use. Users can also manually choose which workspace is used when starting a new chat.

Platform teams control template routing by writing clear template descriptions.
For example, a description like "Use this template for Python backend services
in the payments repo" helps the agent select the correct infrastructure.
Administrators can also block agents on a template, which hides it from the agent completely.
Refer to [Platform Controls](./platform-controls/index.md#template-routing) for that setting.

**Examples of what triggers workspace creation:**

The examples in the first column assume the available tools and context are sufficient.
Any request, including planning or Q&A, can require a workspace if the agent lacks the capabilities or context to complete it.
Creating a workspace doesn't change the current mode's tool restrictions: workspace MCP tools remain unavailable in Plan Mode.
Workspace skills, MCP tools, and context can finish loading after the workspace reports ready.
The agent can continue with available file and shell tools, but provisioning doesn't guarantee immediate access to a missing MCP tool.

| No workspace needed                                  | Workspace provisioned                                    |
|------------------------------------------------------|----------------------------------------------------------|
| "What are the tradeoffs between REST and gRPC?"      | "Find and fix the nil pointer crash in the auth service" |
| "Help me draft an RFC for adding a caching layer"    | "Run the test suite and fix any failures"                |
| "What's the best way to handle retry logic in Go?"   | "Refactor the handler to use the new SDK types"          |
| "Compare connection pooling strategies for Postgres" | "Read the config file and add the new feature flag"      |

### Sub-agents

Coder Agents supports sub-agent delegation. The root agent can spawn child
agents to work on independent tasks in parallel. Each sub-agent gets its own
context window, which keeps individual conversations focused and avoids the
quality degradation that occurs as context windows grow large.

For example, an agent tasked with "explore this repository and document its
structure" might spawn separate sub-agents to analyze the backend, frontend,
and infrastructure directories simultaneously.

### Chat persistence

All chat state is stored in the Coder database, not in the workspace. If a
workspace is stopped, deleted, or rebuilt, the full conversation history
survives. The agent can resume work by creating a new workspace with the same
template and continuing from the last known state, such as a git branch.

### Message queuing

Users can send follow-up messages while the agent is actively working. Messages
are queued and delivered when the agent completes its current step, so there is
no need to wait for a response before providing additional context or changing
direction.

### File attachments

Users can attach files to chat messages by pasting from the clipboard, dragging files into the input area, or using the attachment button.
Supported types are PNG, JPEG, GIF, and WebP images, plus plain text, Markdown, CSV, JSON, SVG, and PDF files.
Each upload can be up to 10&nbsp;MiB.
By default, a chat can have up to 50 attachments.
Adding more permanently deletes the earliest uploads, which then show as expired.
You can change the limit with [`CODER_CHAT_MAX_ATTACHMENTS_PER_CHAT`](../../admin/setup/configuration-reference.md#max-attachments-per-chat).
Attachments are sent to the model as multimodal content alongside the text prompt.

This is useful for sharing screenshots of errors, UI mockups, terminal output, logs, or other context that helps the agent understand the task.
Messages can contain attachments alone or combined with text.
Image attachments require a model that supports vision input, and Anthropic models (including Bedrock-hosted Claude) cap each inline image at 5&nbsp;MiB.
Providers differ in which types they accept as native file content; a part the provider rejects is downgraded to text instead of being dropped.

## Security benefits of the control plane architecture

Running the agent loop in the control plane rather than inside the developer
workspace is an architectural decision that directly addresses the primary
concerns regulated organizations have with AI coding tools: how do you give
developers access to coding agents without introducing unnecessary risk?

Traditionally, agents run inside the same compute where code
lives. This means the agent needs LLM API keys in the workspace, outbound
network access to model providers, and often elevated permissions. In a
regulated environment, this creates a surface area that is difficult to lock
down.

Coder Agents eliminates this by moving the agent loop out of the workspace
entirely:

- **No API keys in workspaces.** LLM provider credentials never enter the
  workspace. The control plane makes all outbound requests to model providers
  directly, so there is nothing for a developer or a compromised process to
  exfiltrate.
- **No agent software to manage.** Workspaces don't need Claude Code, Codex,
  or any agent harness installed. This eliminates a class of supply chain risk
  and removes the need to keep agent software up to date across all workspaces.
- **Network boundaries are simpler.** Because the workspace doesn't need access
  to LLM APIs, you can apply strict egress rules. An agent-only template might
  permit access to only your git provider (e.g., `github.com`) and nothing
  else. The workspace never needs to reach the internet for AI functionality.
- **Centralized, enforced control.** Platform teams configure models, system
  prompts, and tool permissions from the control plane. These settings are
  enforced server-side, so they are not user preferences that developers can
  override.
- **User identity is always attached.** Every action the agent takes — PRs
  opened, code pushed, commands run — is tied to the user who submitted the
  prompt. There is no shared bot identity or anonymous execution.
- **No privilege escalation.** The agent operates with the exact same
  permissions as the user who submitted the prompt. If a developer cannot
  access a template, workspace, or resource through the Coder dashboard,
  the agent cannot access it either. There is no escalation of privileges
  and no shared service account.
- **Workspace isolation is preserved.** The agent can only access workspaces
  owned by the user who submitted the prompt. There is no cross-user
  workspace access — an agent running on behalf of one developer cannot
  read files, execute commands, or interact with another developer's
  workspaces.

> [!TIP]
> For highly sensitive environments, create a dedicated set of templates for
> agent workloads with stricter network policies than your standard developer
> templates. Because the AI comes from the control plane, these templates don't
> need any outbound access to LLM providers.

<!-- break between callouts -->

> [!WARNING]
> By default, agent workspaces have the same network access and permissions
> as any workspace the user creates manually. If your templates do not
> restrict outbound network access, the agent has full internet access from
> the workspace. See [Template Optimization](./platform-controls/template-optimization.md)
> for guidance on configuring network boundaries and scoping credentials for
> agent workloads.

## LLM provider support

Coder Agents works with any LLM provider. Administrators configure providers
and models from the Coder dashboard or API. Supported providers include:

| Provider          | Description                              |
|-------------------|------------------------------------------|
| Anthropic         | Claude models via Anthropic API          |
| OpenAI            | GPT and Codex models via OpenAI API      |
| Google            | Gemini models via Google AI API          |
| Azure OpenAI      | OpenAI models hosted on Azure            |
| AWS Bedrock       | Models available through AWS Bedrock     |
| OpenAI Compatible | Any endpoint implementing the OpenAI API |
| OpenRouter        | Multi-model routing via OpenRouter       |
| Vercel AI Gateway | Models via Vercel AI SDK                 |

Most providers support custom base URLs, which allows integration with
enterprise LLM proxies, self-hosted model endpoints, and internal gateways.

Administrators can configure multiple providers simultaneously and set a default model in each organization.
Developers select from enabled models when starting a chat.
Providers are deployment-wide, and models belong to an organization.
Refer to [Organization scope](./platform-controls/organizations.md) for details.

<img src="../../images/guides/ai-agents/llm-providers.png" alt="Screenshot of the provider/model configuration in the Agents settings">

<small>The model configuration in the Agents settings panel.</small>

## Built-in tools

The agent has access to a set of workspace tools that it uses to accomplish
tasks:

| Tool                                        | Description                                                                                                                                                           |
|---------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `list_templates`                            | Browse available workspace templates                                                                                                                                  |
| `read_template`                             | Get template details and configurable parameters                                                                                                                      |
| `create_workspace`                          | Create a workspace from a template                                                                                                                                    |
| `start_workspace`                           | Start a stopped workspace for the current chat                                                                                                                        |
| `stop_workspace`                            | Stop the current chat's workspace and wait for the stop build to finish                                                                                               |
| `propose_plan`                              | Present a Markdown plan file for user review                                                                                                                          |
| `ask_user_question`                         | Ask the user structured clarification questions during plan mode                                                                                                      |
| `read_file`                                 | Read file contents from the workspace                                                                                                                                 |
| `write_file`                                | Write a file to the workspace                                                                                                                                         |
| `edit_files`                                | Replace `old_text` with `new_text` across files                                                                                                                       |
| `execute`                                   | Run shell commands in the workspace                                                                                                                                   |
| `process_output`                            | Retrieve output from a background process                                                                                                                             |
| `process_list`                              | List all tracked processes in the workspace                                                                                                                           |
| `process_signal`                            | Send a signal (terminate/kill) to a tracked process                                                                                                                   |
| `attach_file`                               | Attach a workspace file to the chat as a durable downloadable attachment                                                                                              |
| `spawn_agent` (`type=general` or `explore`) | Delegate a task to a sub-agent running in parallel, optionally on a specific model                                                                                    |
| `list_subagent_models`                      | List the models available for `spawn_agent`'s `model_config_id` argument                                                                                              |
| `wait_agent`                                | Wait for a sub-agent to complete and collect its result                                                                                                               |
| `message_agent`                             | Send a follow-up message to a running sub-agent                                                                                                                       |
| `interrupt_agent`                           | Halt a sub-agent's current turn; it transitions to waiting or running if there are queued messages                                                                    |
| `spawn_agent` (`type=computer_use`)         | Spawn a sub-agent with desktop interaction (screenshot, mouse, keyboard)                                                                                              |
| `list_agents`                               | List spawned child agents, most recently active first                                                                                                                 |
| `read_skill`                                | Read the instructions for a workspace skill by name                                                                                                                   |
| `read_skill_file`                           | Read a supporting file from a skill's directory                                                                                                                       |
| `web_search`                                | Search the internet (provider-native, when enabled)                                                                                                                   |
| `find_tools`                                | Search the deferred MCP tool catalog and activate matching tools. Only available when the `mcp-tool-search` experiment is enabled and the turn has MCP tools to defer |

These tools connect to the workspace over the same secure connection used for
web terminals and IDE access. No additional ports or services are required in
the workspace.

Platform tools (`list_templates`, `read_template`, `create_workspace`,
`start_workspace`, `stop_workspace`, `propose_plan`, `ask_user_question`) and orchestration tools (`spawn_agent`,
`list_subagent_models`, `wait_agent`, `message_agent`, `interrupt_agent`, `list_agents`)
are only available to root chats. Sub-agents do not have access to these
tools and cannot create workspaces or spawn further sub-agents.

`spawn_agent` with `type=computer_use` additionally requires an
Anthropic or OpenAI provider and the virtual desktop feature to be
enabled by an administrator.
`read_skill` and `read_skill_file` are available when the workspace contains
skills in its `.agents/skills/` directory.

`propose_plan` and `ask_user_question` are only available while plan mode is active.
In plan mode, the agent can still inspect the workspace and template metadata, execute shell commands for exploration, and read process output.
`write_file` and `edit_files` remain available only for the chat-specific plan file under `.coder/plans/`.
Workspace MCP tools are unavailable in plan mode, and plan-mode sub-agents receive no MCP tools.

## Plan mode

Plan mode lets you ask the agent to investigate first and present a plan before
implementation. Open the chat input menu and choose **Plan first** to enable it
for the current chat.
After you enable it, later turns in that chat stay in plan mode until you turn it off or select **Implement plan** after a proposed plan.
Because the mode is stored on the chat, reloading the page preserves the current setting.

While plan mode is active:

- The agent can inspect repository files, workspace state, and available templates.
- `write_file` and `edit_files` can only modify the chat-specific plan file under `.coder/plans/`.
- `ask_user_question` can gather structured clarification from the user before a plan is proposed.
- `propose_plan` snapshots the current plan file into the transcript so you can review it before implementation starts.
- `execute` and `process_output` remain available for exploration, such as cloning repositories, searching code, and running inspection commands.
- External MCP tools are available to root chats only for the server configurations an administrator approved for plan mode; workspace MCP tools and MCP tools for plan-mode sub-agents are not available.
- Dynamic tools, provider-native tools, and computer-use tools are not available.
- Root plan-mode chats can also use external MCP tools that an administrator approved for plan mode.

This keeps planning turns focused on analysis and plan authoring rather than implementation.
Once you select **Implement plan**, the next turn runs in normal mode again.

---

# Getting Started

Source: https://coder.com/docs/ai-coder/agents/getting-started

This guide walks platform teams and administrators through setting up Coder
Agents, preparing your deployment, and running your first Coder Agent.

## Prerequisites

Before you begin, confirm the following:

- **Coder deployment** running the latest release.
- **LLM provider credentials** — an API key for at least one
  [supported provider](./models.md) (Anthropic, OpenAI, Google, Azure OpenAI,
  AWS Bedrock, OpenAI Compatible, OpenRouter, or Vercel AI Gateway).
- **Network access** from the control plane to your LLM provider. Workspaces
  do not need LLM access — only the control plane does.
- **At least one template** with a
  [descriptive name and description](./platform-controls/template-optimization.md)
  for the agent to select when provisioning workspaces.
- **Admin access** to the Coder deployment for configuring providers.
- **Access to configure models** in each organization where you configure models.
  The **Organization Admin** role and the **Owner** role include this access.
  A custom role with model configuration access also works.
- **Organization membership** for each user who uses Coder Agents.
  Every organization member can use Coder Agents by default.
  To restrict access, see [Control who can use Coder Agents](#control-who-can-use-coder-agents).
  Users also need read access to at least one model in the organization.
  New models are shared with the whole organization by default.
  See [Manage model permissions](./models.md#manage-model-permissions).

## Step 1: Configure an LLM provider and model

> [!IMPORTANT]
> Deployment administrators configure providers and deployment settings.
> Users with model configuration access in an organization configure that organization's models.
> Coder enables the edit controls for the organization that you select.
> Coder shows the deployment settings only to deployment administrators.
> Users with model access can view the relevant Models and Coder Agents pages.
> Users with MCP server access can open the MCP servers page.

To configure Coder Agents:

1. Navigate to **Admin settings** > **AI** and select **Providers**.
1. Add or update a provider with its credentials and upstream endpoint, then
   save it.
1. Navigate to **Admin settings** > **AI** > **Models**.
1. Select the correct organization.
   Coder shows the organization picker when you can access more than 1 organization.
1. Select **Add model** and configure at least one model with its identifier, display name, and context limit.

Coder makes the first model of an organization the default model.
To change the default later, open a model and select **Set as Coder Agents default model**, or pick a model in the **Default model** row under **Admin settings** > **AI** > **Coder Agents** > **Organization settings**.

Each organization has its own model list and its own default model.
Repeat the model steps in every organization that uses Coder Agents.
Refer to [Organization scope](./platform-controls/organizations.md) for the settings that stay deployment-wide.

Detailed instructions for each provider and model option are in the
[Models](./models.md) documentation.

> [!TIP]
> Start with a single frontier model to validate your setup before adding
> additional providers.

## Step 2: Start your first Coder Agent

1. Go to the **Agents** page in the Coder dashboard.
1. Select a model from the dropdown (your default will be pre-selected).
1. Type a prompt and send it.

The agent processes the prompt in the control plane.
When the conversation and available tools are sufficient, it works without provisioning a workspace.
If missing tools, skills, MCP integrations, or context block progress, the agent selects a template and provisions a workspace to continue.
It also provisions a workspace for tasks that need file access, command execution, or code changes.

## Control who can use Coder Agents

Organization members can use Coder Agents by default.
Access comes from the **Coder Agents User** (`agents-access`) organization role, which each organization grants to members through its [default member roles](../../admin/users/organizations.md#default-member-roles).

Members who don't hold the role directly lose Coder Agents access when you remove **Coder Agents User** from the default roles.
Role sync assigns roles at sign-in and doesn't store default roles, so members who get the role through role sync regain access at their next sign-in, and mapping the role in advance doesn't shorten the gap.

To limit Coder Agents to a subset of members in an organization (requires a Premium license):

1. Remove **Coder Agents User** from the organization's default roles.
   In the dashboard, go to **Admin settings** > **Organizations** > **Roles** > **Default Roles**.
   From the CLI, run `coder organizations edit --org <organization> --default-org-member-roles organization-workspace-access`, keeping any other default roles in the list.
1. Grant `agents-access` to the members who need it:
   - With [IdP organization role sync](../../admin/users/idp-sync.md#role-sync), map an IdP group or role to `agents-access`.
   - Without role sync, assign **Coder Agents User** from **Admin settings** > **Organizations** > **Members**.

Keep the following behavior in mind:

- Removing a user from the mapped IdP group or role removes their Coder Agents access at their next sign-in.
- Owners and Organization Admins can always use Coder Agents, whatever the default roles are.
- Service accounts don't inherit `agents-access` from the default roles.
  Assign the role to a service account directly if it needs Coder Agents.
- Members without the role can't use Coder Agents or open chats they created earlier.
  Their chats are kept and become available again when they regain the role.
  A chat shared with them stays readable.
- [Model permissions](./models.md#manage-model-permissions) still apply: users also need read access to at least one model.

## Optimize your templates

The agent selects templates based on their **name, description, and README**.
It does not read Terraform. Clear, specific descriptions are the most important
factor in whether the agent picks the right template.

Update your template descriptions to include:

- The language, framework, or stack the template targets.
- Which repository or service it is for, if applicable.
- What type of work it supports (backend, frontend, data pipeline, etc.).

When 128 characters is not enough, put the most important routing context near
the top of the template's
[`README.md`](./platform-controls/template-optimization.md#put-routing-context-near-the-top-of-the-readme).
The chat agent's template listing includes a bounded README excerpt (roughly the
first 1,000 characters), and template detail includes the README (up to roughly
8,000 characters). Both are reduced to plain text: frontmatter is stripped,
link text is kept while link URLs are dropped, images and badges are dropped
entirely, and code blocks and tables are preserved as text.

**Good examples:**

| Description                                                                                 | Why it works                                 |
|---------------------------------------------------------------------------------------------|----------------------------------------------|
| Python backend services for the payments repo. Includes Poetry, Python 3.12, and PostgreSQL | Specific language, repo, and toolchain       |
| React frontend development for the customer portal. Node 20, pnpm, Storybook pre-installed  | Clear stack, named project, key tools listed |
| General-purpose Go development environment with Go 1.23, Docker, and common CLI tools       | Broad but descriptive                        |

**Descriptions to avoid:**

| Description        | Problem                                         |
|--------------------|-------------------------------------------------|
| Team A template v2 | No information about what the template is for   |
| Dev environment    | Too generic to distinguish from other templates |
| Default            | Tells the agent nothing                         |

See [Template Optimization](./platform-controls/template-optimization.md) for
the full guide, including dedicated agent templates, network boundaries,
credential scoping, and pre-installing dependencies.

## Things to know before you start

### Plan for change between releases

Coder Agents is generally available.
However, APIs, behavior, and configuration may change between releases.
As always, you should review [release notes](https://github.com/coder/coder/releases) and the [changelog](https://coder.com/changelog) before upgrading, so changes do not affect production.

### Use HTTPS for push notifications

Coder Agents use browser push notifications to alert you when a task
completes or needs attention. Most browsers require a secure (HTTPS)
origin for the [Push API](https://developer.mozilla.org/en-US/docs/Web/API/Push_API)
to work. If your access URL uses plain HTTP,
push notifications may not function.

This does not affect agents themselves — only the browser notification
delivery. If you terminate TLS at a reverse proxy, ensure the
[access URL](../../admin/setup/index.md) is configured with an `https://` scheme.

### Set a deployment-wide system prompt

Administrators can set a system prompt that applies to all Coder Agents across the
deployment. Use this to encode organizational conventions:

- Coding standards and style guidelines.
- Commit message formats.
- Branch naming conventions.
- Required review processes before merging.
- Any guardrails specific to your environment.

Configure the system prompt from **Admin settings** > **AI** > **Coder Agents** > **Instructions**
or via the API at `PUT /api/v2/chats/config/system-prompt`.
See [Platform Controls](./platform-controls/index.md) for details.

### Understand the security model

The agent runs in the control plane, not inside workspaces. This means:

- **No LLM API keys in workspaces.** Credentials stay in the control plane.
- **No agent software in workspaces.** No supply chain risk from
  third-party agent tools.
- **User identity is always attached.** Every action is tied to the user
  who submitted the prompt — no shared bot accounts.
- **No privilege escalation.** The agent has exactly the same permissions
  as the prompting user.

Agent workspaces inherit the same network access as any manually created
workspace. If your templates don't restrict egress, the agent has full
internet access from the workspace. Consider
[creating dedicated agent templates](./platform-controls/template-optimization.md#create-dedicated-agent-templates)
with tighter network policies.

### Plan for LLM costs

Every conversation turn sends tokens to your LLM provider. Long-running tasks,
sub-agent delegation, and complex multi-step work can consume significant
token volume. Consider:

- Starting with a single model to establish a cost baseline.
- Capping spend with [AI Gateway budgets](./platform-controls/spend-management.md).
- Monitoring provider dashboards for usage trends as adoption grows.

### Plan for concurrency limits

Community licenses run up to 5 agents at once.
Additional agents queue and start automatically when capacity frees.
A Premium license with Agent Hours does not impose a concurrency limit unless the Agent Hours hard limit is reached.
If the Agent Hours allocation is exhausted without a configured hard limit, Coder warns about usage but does not impose a concurrency limit.
When the Agent Hours hard limit is reached, additional agents queue under the concurrency limit.
Refer to [Concurrent agents](./platform-controls/index.md#concurrent-agents) for details.

### Pilot with a small group

Identify 3–5 developers and a few concrete use cases for the initial rollout.
Good starting points:

- **Low-risk, high-visibility tasks** — generating unit tests, writing inline
  documentation, small refactors.
- **Investigation and triage** — exploring unfamiliar code, triaging bugs,
  understanding legacy systems.
- **Prototyping** — building proof-of-concept implementations, simple
  dashboards, internal tools.

To limit Coder Agents to the pilot group, see [Control who can use Coder Agents](#control-who-can-use-coder-agents).

Set expectations for how the team reviews agent output.
Developers should still review all agent-produced code before merging.
The agent is a force multiplier, not a replacement for developer judgment.

### Use the API for programmatic automation

The [Chats API](../../reference/api/chats.md) enables programmatic access to Coder Agents.
This is useful for building automations such as:

- Triggering Coder Agents from CI/CD pipelines when builds fail.
- Creating Coder Agents from GitHub webhooks on new issues or PRs.
- Building internal tools or dashboards on top of the API.
- Scripting batch operations across repositories.

**Quick example — create a Coder Agent via the API:**

```sh
curl -X POST https://coder.example.com/api/v2/chats \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": [
      {"type": "text", "text": "Fix the failing tests in the auth service"}
    ]
  }'
```

Stream updates in real time by connecting to the WebSocket endpoint:

```txt
GET /api/v2/chats/{chat}/stream
```

For service-to-service automation, use
[API keys](../../admin/users/sessions-tokens.md)
rather than developer session tokens. Keep automation credentials
narrowly scoped.

### Link to a new chat with a prompt

To send users to a new chat with a message already written, link to `/agents` with a `prompt` query parameter.
URL-encode the message (for example, with `encodeURIComponent` in JavaScript):

```txt
https://coder.example.com/agents?prompt=Fix%20the%20failing%20tests%20in%20the%20auth%20service
```

The link fills in the message box only.
Coder doesn't send the message: the user reviews it, can edit it, and selects **Send**.
Because any website can create such a link, a warning in the message box asks the user to take care before sending.
The warning disappears once the user edits the message.

If the user isn't signed in, Coder keeps the message through sign-in.

Don't put secrets in these links.
URLs end up in browser history and server logs.

### Add workspace context with AGENTS.md

Create an `AGENTS.md` file in the home directory (`~/.coder/AGENTS.md`) or
the workspace agent's working directory to provide persistent context to the
agent. This file is automatically read and included in the system prompt
for every conversation with a Coder Agent that uses that workspace.

Use it for:

- Repository-specific build and test instructions.
- Important architectural decisions or constraints.
- Links to relevant documentation or runbooks.
- Any context that helps the agent work effectively in that codebase.

### Consider prebuilt workspaces for faster startup

Workspace provisioning is the main source of latency when the agent starts a
task. If your templates take more than a minute to provision, consider
configuring
[prebuilt workspaces](../../admin/templates/extending-templates/prebuilt-workspaces.md)
to maintain a pool of ready-to-use workspaces. The agent gets assigned an
already-running workspace instead of provisioning from scratch.

<a id="providing-feedback"></a>

## Provide feedback

Report bugs and feature requests as [GitHub issues](https://github.com/coder/coder/issues/new/choose).
For deployment-specific problems, such as provider configuration or performance in your environment, use your usual Coder support channel.

Good reports include:

- **What you tried**: the prompt, the template, and the model.
- **What happened**: the agent's behavior, any errors, and unexpected results.
- **What you expected**: the outcome you were looking for.
- **Context**: screenshots, `chat_id` values, or links to the Agents page help
  the team investigate quickly.

## Next steps

- [Architecture](./architecture.md) — how the control plane, LLM providers,
  and workspaces interact.
- [Models](./models.md) — configure additional providers and models.
- [Platform Controls](./platform-controls/index.md) — system prompts,
  template routing, and admin-level configuration.
- [Template Optimization](./platform-controls/template-optimization.md) —
  create agent-friendly templates with network boundaries and scoped
  credentials.
- [Chats API](../../reference/api/chats.md): build programmatic integrations.

---

# Architecture

Source: https://coder.com/docs/ai-coder/agents/architecture

Coder's AI agent interacts with workspaces over the same
connection path as a developer's IDE, web terminal, and SSH session already
use. There is no sidecar process and no new network paths. If your developers
can already connect to their workspaces, the agent can too.

## Architecture at a glance

Three components are involved in every agent interaction:

1. **The control plane** runs the agent loop. It receives prompts, streams them
   to the LLM provider, interprets tool calls, and dispatches them to
   workspaces.
1. **The LLM provider** (Anthropic, OpenAI, Google, Azure, AWS Bedrock, or any
   OpenAI-compatible endpoint) performs model inference. It never communicates
   with the workspace directly.
1. **The workspace** is standard compute infrastructure. It runs shell commands,
   reads and writes files, and executes processes — exactly what occurs when a
   developer connects via their IDE.

<img src="../../images/guides/ai-agents/agent-loop-detailed.png" alt="Architecture diagram">

## The same connection your IDE uses

This is the key architectural insight: the agent reaches into a workspace
over the same Tailnet tunnel that a developer's tools already use.

When a developer opens a web terminal in the Coder dashboard, connects via
VS Code Remote, or runs `coder ssh`, the traffic follows this path:

1. The client connects to the control plane.
1. The control plane routes the connection through its internal Tailnet node.
1. The connection reaches the workspace daemon over a DERP relay or
   direct peer-to-peer link.
1. The workspace daemon handles the request — spawning a shell,
   forwarding a port, or serving a file.

When the agent executes a tool call — reading a file, running a command,
writing code — it follows the same tunnel:

1. The agent loop in the control plane issues a tool call.
1. The control plane routes the call through its internal Tailnet node.
1. The call reaches the workspace daemon over the same DERP relay or
   peer-to-peer link.
1. The workspace daemon handles the request via its HTTP API — reading a file,
   starting a process, or writing content.

The underlying tunnel is identical. IDE connections use SSH, web terminals use
a WebSocket protocol, and the agent uses the workspace daemon's HTTP API — but
all three traverse the same Tailnet connection and rely on the same security
boundary. No additional ports or network paths are introduced.

### No inbound ports

The workspace daemon always dials _out_ to the control plane — never
the reverse. The control plane then uses that established tunnel to reach back
in. This means:

- The workspace needs no inbound ports or exposed services.
- You can block all inbound traffic to the workspace.
- The only required outbound connection from the workspace is to the control
  plane itself.

This is unchanged from how workspaces already operate in Coder. Enabling
Coder Agents does not change your workspace network requirements.

## The agent loop

When a user submits a prompt, the control plane processes it as a background
job:

1. The prompt is saved to the database and the chat is marked `running`.
1. A chat worker in the control plane claims the chat and starts a turn.
1. The control plane streams the conversation to the configured LLM provider.
1. The model responds with text, reasoning, or tool calls.
1. If the response includes tool calls, the control plane executes them
   (connecting to the workspace as needed) and returns the results to the model.
1. Steps 3–5 repeat until the model produces a final response with no further
   tool calls.
1. The chat is marked `waiting` for the next user message.

This loop runs inside the control plane process. There is no separate service
to deploy — it is part of the same binary that serves the dashboard and API.

### Context compaction

As conversations grow, the agent automatically summarizes older context to stay
within the model's context window. When token usage exceeds a threshold, the
agent generates a compressed summary and inserts it as a new message. Earlier
messages remain in the database and are still visible to users, but are excluded
from the model's context window. This happens transparently and keeps
long-running sessions productive.

You can also trigger a compaction on demand by sending `/compact` while the
agent is idle or in an error state, which clears the error. Manual compaction
runs the same summarization regardless of current token usage and is labeled
as manual in the conversation.

To start over without a summary, send `/clear` while the agent is idle or in
an error state. The transcript stays visible, but the next message runs with
a fresh context, as if the conversation were new. A "Context cleared" marker
shows where the reset happened.

### Message queuing

Users can send follow-up messages while the agent is actively working. Messages
are queued in the database and delivered when the agent completes its current
turn — the full sequence of steps until the model stops calling tools. There is
no need to wait for a response before providing additional context or
redirecting the agent.

## Tool execution

Tools are how the agent takes action. Each tool call from the LLM translates to
a concrete operation — either inside a workspace or within the control plane
itself.

The agent is restricted to the built-in tool set defined in this section,
plus any additional tools from workspace skills and MCP servers. Skills
provide structured instructions the agent loads on demand
(see [Extending Agents](./extending-agents.md)). MCP tools come from
admin-configured external servers
(see [MCP Servers](./platform-controls/mcp-servers.md)) and from workspace
`.mcp.json` files. The agent has no direct access to the Coder API beyond
what these tools expose and cannot execute arbitrary operations against the
control plane.

### Workspace connection lifecycle

The connection to a workspace is **lazy**. It is not established when a chat
starts — only when something needs to reach the workspace. This is typically
triggered by the first tool call that requires workspace access. Once
established, the connection is cached and reused for the duration of that chat
session.

Chats that don't need workspace access (answering questions, planning an
approach, discussing architecture) never provision or connect to a workspace.

### Workspace tools

These tools execute inside the workspace via the workspace daemon's HTTP API.
They traverse the same Tailnet tunnel used by web terminals and IDE connections.

| Tool             | What it does                                                                                                                                                                                                                                                                       |
|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `read_file`      | Reads file contents with line-number pagination.                                                                                                                                                                                                                                   |
| `write_file`     | Writes content to a file.                                                                                                                                                                                                                                                          |
| `edit_files`     | Performs atomic, per-file edits across one or more files, replacing `old_text` with `new_text`.                                                                                                                                                                                    |
| `execute`        | Runs a shell command, waiting for completion up to a timeout.                                                                                                                                                                                                                      |
| `process_output` | Retrieves output from a tracked process.                                                                                                                                                                                                                                           |
| `process_list`   | Lists all tracked processes in the workspace.                                                                                                                                                                                                                                      |
| `process_signal` | Sends a signal (SIGTERM or SIGKILL) to a tracked process.                                                                                                                                                                                                                          |
| `attach_file`    | Attach a workspace file to the current chat so the user can download it directly from the conversation. Use this when the user should receive an artifact such as a screenshot, log, patch, or document. Pass an absolute file path. The file must already exist in the workspace. |

#### Windows workspace shell requirement

Coder Agents run workspace commands through a POSIX-compatible shell (`sh`).
Windows workspaces must provide `sh` on `PATH`, for example from
[Git for Windows](https://gitforwindows.org/) (Git Bash), MSYS2, or WSL.
PowerShell alone cannot run the `execute` tool. After installing a
shell, restart the workspace to pick up the updated `PATH`.

### Platform tools

These tools run entirely within the control plane. They do not require a
workspace connection. Platform and orchestration tools are only available to
root chats — sub-agents spawned by `spawn_agent` do not have access to them
and cannot create workspaces or spawn further sub-agents.

| Tool                | What it does                                                                                      |
|---------------------|---------------------------------------------------------------------------------------------------|
| `list_templates`    | Browses available workspace templates, sorted by popularity.                                      |
| `read_template`     | Gets template details and configurable parameters.                                                |
| `create_workspace`  | Creates a workspace from a template and waits for it to be ready.                                 |
| `start_workspace`   | Starts the chat's workspace if it is currently stopped. Idempotent if already running.            |
| `stop_workspace`    | Stops the chat's workspace and waits for the stop build to finish. Idempotent if already stopped. |
| `propose_plan`      | Presents a Markdown plan file from the workspace for user review before implementation.           |
| `ask_user_question` | Asks the user structured clarification questions during plan mode.                                |

`propose_plan` and `ask_user_question` are only exposed while plan mode is
active. In that mode, `write_file` and `edit_files` are restricted to the
chat-specific plan file, while `execute` and `process_output` remain available
for exploration such as cloning repositories, searching code, and running
inspection commands. Root plan-mode chats may also receive administrator-approved
external MCP tools. Workspace MCP tools remain unavailable in plan mode, and
plan-mode sub-agents still do not receive any MCP tools. Dynamic,
provider-native, and computer-use tools are not available.

### Orchestration tools

These tools manage sub-agents — child chats that work on independent tasks in
parallel.

| Tool                                        | What it does                                                                                                                                                                                                                                                         |
|---------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `spawn_agent` (`type=general` or `explore`) | Delegates a task to a sub-agent with its own context window. Optionally accepts `model_config_id` and `reasoning_effort` to run the child on a specific enabled model instead of the configured default.                                                             |
| `list_subagent_models`                      | Lists the enabled model configurations the agent can pass to `spawn_agent` as `model_config_id`.                                                                                                                                                                     |
| `wait_agent`                                | Waits for a sub-agent to finish and collects its result.                                                                                                                                                                                                             |
| `message_agent`                             | Sends a follow-up message to a running sub-agent.                                                                                                                                                                                                                    |
| `interrupt_agent`                           | Halts a sub-agent's current turn; it transitions to waiting or running if there are queued messages.                                                                                                                                                                 |
| `spawn_agent` (`type=computer_use`)         | Spawns a sub-agent with desktop interaction capabilities (screenshot, mouse, keyboard). Requires an administrator-configured computer-use provider (Anthropic or OpenAI) and the [virtual desktop experiment](./platform-controls/virtual-desktop.md) to be enabled. |
| `list_agents`                               | Lists spawned child agents, most recently active first.                                                                                                                                                                                                              |

### Provider tools

These tools are executed server-side by the LLM provider, not by the control
plane or workspace. They are conditionally available based on the model
configuration set by an administrator.

| Tool         | What it does                                                                                                                                     |
|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| `web_search` | Searches the internet for up-to-date information. Available when web search is enabled for the configured Anthropic, OpenAI, or Google provider. |

### Workspace extension tools

These tools are conditionally available based on the workspace contents.

| Tool              | What it does                                                                                                                   |
|-------------------|--------------------------------------------------------------------------------------------------------------------------------|
| `read_skill`      | Reads the instructions for a workspace skill by name. Available when the workspace has skills discovered in `.agents/skills/`. |
| `read_skill_file` | Reads a supporting file from a skill's directory.                                                                              |

### MCP tool search

This tool runs in the control plane and replaces the full MCP tool schemas with a searchable catalog, so a large MCP surface does not consume the context window.

| Tool         | What it does                                                                                                                                                                                           |
|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `find_tools` | Searches the deferred MCP tool catalog by keyword or exact name and activates the matching tools. Available only when the `mcp-tool-search` experiment is enabled and the turn has MCP tools to defer. |

## What runs where

Understanding the split between the control plane and the workspace is central
to the security model.

| Responsibility      | Where it runs | Details                                                                   |
|---------------------|---------------|---------------------------------------------------------------------------|
| Agent loop          | Control plane | Prompt processing, tool dispatch, step iteration.                         |
| LLM inference       | LLM provider  | The control plane streams requests to the external provider.              |
| Chat state          | Control plane | All messages, token usage, and status stored in the database.             |
| Git authentication  | Control plane | Uses existing Coder external auth (GitHub, GitLab, Bitbucket).            |
| User identity       | Control plane | Every action is tied to the user who submitted the prompt.                |
| Model/prompt config | Control plane | Administrators configure providers, models, and system prompts centrally. |
| File read/write     | Workspace     | The workspace file system is the source of truth for code.                |
| Shell execution     | Workspace     | Commands run in the workspace's environment with its packages and tools.  |
| Git operations      | Workspace     | Commits, pushes, and branch management happen inside the workspace.       |
| Build and test      | Workspace     | Compilation, test suites, and dev servers run on workspace compute.       |

The workspace has **zero AI awareness**. There are no LLM API keys, no agent
processes, and no AI-specific software installed. If you inspect a workspace
created by the agent, it looks identical to one a developer created
manually.

## Chat state and persistence

All chat data is stored in the control plane database, not in the workspace.

- **Chat metadata** — status, owner, associated workspace, timestamps, and
  parent/child relationships for sub-agents.
- **Messages** — every message (user, assistant, tool calls, tool results) is
  stored as a separate record with role, content, and token usage.
- **Compressed context** — when the agent compacts the conversation, summaries
  are stored with a compression flag so the original context budget is
  preserved.
- **Queued messages** — follow-up messages sent while the agent is working are
  held in a queue and delivered in order.

Because state lives in the database:

- Chat history survives workspace stops, rebuilds, and deletions.
- An administrator can inspect any chat for audit or debugging.
- The agent can resume work by targeting a new workspace and continuing from the
  last git branch or checkpoint.

## Security posture

The control plane architecture provides built-in security properties for AI
coding workflows. These are structural guarantees, not configuration options —
they hold by default for every agent session.

### No API keys in workspaces

LLM provider credentials exist only in the control plane. The workspace never
sees them. There is nothing for a developer, a compromised dependency, or a
rogue process to exfiltrate.

### Workspaces can be fully network-isolated

Because the workspace does not need to reach any LLM provider, you can restrict
its network access to only:

- The control plane (required for the workspace daemon to function).
- Your git provider (for push/pull operations).

Everything else can be blocked. The AI functionality comes from the control
plane, not from the workspace's network.

> [!TIP]
> For sensitive environments, create dedicated templates for agent workloads
> with stricter egress rules than your standard developer templates. Because
> the AI comes from the control plane, these templates do not need any
> outbound access to LLM providers.

### Centralized enforcement

Administrators control which models are available, the system prompt, and tool configuration from the control plane.
The system prompt and the tool configuration are deployment-wide.
The model list belongs to an organization, so a chat can only use the models of its own organization.
Developers can select from the set of admin-enabled models when starting or continuing a chat, but cannot add their own providers or override system prompts or tool permissions.
When an administrator removes a model or modifies the system prompt, the change applies to all affected agent sessions immediately.
Refer to [Organization scope](./platform-controls/organizations.md) for the settings that belong to each scope.

### User identity on every action

Every action the agent takes — PRs opened, code committed, commands executed —
is tied to the user who submitted the prompt. There is no shared bot account or
anonymous identity. If a developer submits a prompt that results in a pull
request, that pull request is attributed to them via the git authentication
already configured in your Coder deployment.

### Permission boundaries

The agent operates with the exact same permissions as the user who submitted
the prompt. If a user cannot access a template, workspace, or API endpoint
through the Coder dashboard or CLI, the agent cannot access it either. There
is no privilege escalation.

This extends to workspace isolation: the agent can only interact with
workspaces owned by the user who started the chat. It cannot read files,
execute commands, or connect to workspaces belonging to other users.

Template visibility follows the same rule. When the agent lists available
templates, it sees only the templates the user is authorized to access.
The agent cannot provision a workspace from a template the user does not
have permission to use.

## Scaling and resource impact

The control plane overhead for Coder Agents is minimal. The heavy computation
happens elsewhere:

- **LLM inference** runs on the external provider's infrastructure.
- **File I/O, builds, and tests** run on workspace compute.
- **The control plane** primarily proxies streaming responses and dispatches
  tool calls over existing network connections.

---

# Platform Controls

Source: https://coder.com/docs/ai-coder/agents/platform-controls

## Design philosophy

Coder Agents is built on a simple premise: platform teams should have full
control over how agents operate, and developers should have zero configuration
burden.

This means:

- **All agent configuration is admin-level.** Providers, models, system prompts, and tool permissions are set by administrators from the control plane.
  These are not user preferences.
  Deployment administrators own the deployment-wide policies.
  Users with organization configuration access own the models and the MCP servers of their organization.
  Refer to [Organization scope](./organizations.md) for the split between the 2 scopes.
- **Developers never need to configure anything by default.** A developer just
  describes the work they want done. They do not need to pick a provider or
  write a system prompt. The platform team has already set all of that up.
  When a platform team enables user API keys for a provider, developers may
  optionally supply their own key, but this is an opt-in policy decision, not
  a requirement.
- **Enforcement, not defaults.** Settings configured by administrators are enforced server-side.
  Developers cannot override them.
  A setting that a user can change is a preference, not a policy.

This is an architectural decision, not just a product choice. Because the agent
loop runs in the control plane rather than inside developer workspaces, there is
no local configuration for developers to modify and no agent software for them
to reconfigure. The control plane is the single source of truth for how agents
behave.

## What platform teams control today

### Providers and models

Administrators configure which LLM providers and models are available from the
Coder dashboard. This includes API keys, base URLs (for enterprise proxies or
self-hosted models), and per-model parameters like context limits, thinking
budgets, and reasoning effort.

Providers are deployment-wide.
Models belong to an organization, so each organization has its own model list and its own default model.

Developers select from the set of models an administrator has enabled. They
cannot add their own providers or access models that have not been explicitly
configured.

When an administrator enables user API keys on a provider, developers can
supply their own key from the Agents settings page. Refer to
[User API keys (BYOK)](../models.md#user-api-keys-byok) for details.

An administrator can also enable personal model overrides, which let a developer
select a different model for their own chats. Coder disables personal model
overrides until an administrator enables them.

Refer to [Models](../models.md) for setup instructions.
Refer to [Organization scope](./organizations.md) for the organization scope and the upgrade behavior.

### System prompt

Administrators can set a system prompt that applies to all agent sessions. This
is useful for establishing organizational conventions: coding standards,
commit message formats, preferred libraries, or repository-specific context.

This setting is available under **Admin settings** > **AI** > **Coder Agents** > **Instructions** and is only accessible to administrators. Developers can't access or interact with it.

### Plan mode instructions

Administrators can add deployment-wide instructions that apply only when a chat
enters plan mode. These instructions supplement the built-in planning behavior
and are useful for organization-specific planning requirements such as required
plan sections, approval checkpoints, or review workflows.

This setting is available under **Admin settings** > **AI** > **Coder Agents** > **Instructions**. Developers do not edit it directly.

The same value is exposed over the chat configuration API:

- `GET /api/v2/chats/config/plan-mode-instructions`
- `PUT /api/v2/chats/config/plan-mode-instructions`

### Template routing

Platform teams control which templates are available to agents and how the agent
selects them. When a developer describes a task, the agent reads template
descriptions to determine which template to provision.

By writing clear template descriptions, for example, "Use this template for
Python backend services in the payments repo", platform teams can guide the
agent toward the correct infrastructure without requiring developers to
understand template selection at all.

Administrators can also restrict which templates are available to agents at **Admin settings** > **AI** > **Coder Agents** > **Templates**.
Use the switch for each template in the list.
The same control is available on each individual template's settings page as **Allow Coder Agents to create workspaces using this template**.
Templates allow agents by default.
When you disable the control, the agent cannot read the template or provision workspaces from it.
This is separate from what developers observe when manually creating workspaces, so you can apply stricter policies to agent-created workspaces without affecting the manual workspace experience.

The same control is available outside the dashboard.
Use `coder templates create --agents-allowed=false` or `coder templates edit --agents-allowed=false <template>` for a single template.
Use the search filter `agents-allowed:false` on `GET /api/v2/templates` to list the templates that block agents.

Check out [Template Optimization](./template-optimization.md) for best practices on writing discoverable descriptions, restricting template visibility, configuring network boundaries, scoping credentials, and designing template parameters for agent use.

### MCP servers

Administrators can register external MCP (Model Context Protocol) servers that
provide additional tools for agent chat sessions. This includes configuring
authentication, controlling which tools are exposed via allow/deny lists, and
setting availability policies that determine whether a server is mandatory,
opt-out, or opt-in for each chat.

Each organization has its own set of MCP servers.

Refer to [MCP Servers](./mcp-servers.md) for configuration details.

### Workspace autostop fallback

Administrators can set a default autostop timer for agent-created workspaces
that do not define one in their template. Template-defined autostop rules always
take precedence. Active conversations extend the stop time automatically.

This setting is available under **Admin settings** > **AI** > **Coder Agents** > **Lifecycle**.
The maximum configurable value is 30&nbsp;days.
When disabled, workspaces follow their template's autostop rules (or none, if the template does not define any).

### Concurrent agents

Community licenses support up to 5 concurrently active agents.
Coder doesn't limit how long those agents can run or how many tasks they complete over time.
Additional agents queue until an agent session becomes available.
With concurrent agents, individuals and small teams can experiment with Coder Agents at no cost.

Queued agents show a banner in the chat and start automatically when capacity frees.
Subtasks delegated by an agent don't count toward this limit.
Those subtasks run in a separate pool of up to 10 concurrent subtasks.

Deployments with a Premium license can purchase Agent Hours.
Agent Hours are shared across the deployment, and agents can run concurrently unless the Agent Hours hard limit is reached.
If the Agent Hours allocation is exhausted without a configured hard limit, Coder warns about usage but does not impose a concurrency limit.
When the Agent Hours hard limit is reached, additional agents queue under the concurrency limit.

### Spend management

AI Gateway budgets cap each user's AI spend, including Coder Agents chats, over a monthly period.
Coder sets budgets per group, and the deployment policy selects the group with the largest spend limit when a user belongs to several budgeted groups.
A per-user override takes priority over all group budgets.

Budgets are the only spend cap for Coder Agents chats.
Chats no longer enforce a separate limit of their own, and existing native limit values are not migrated to budgets.
Budget controls in the Coder UI, the group budget endpoints, and the AI spend status endpoints all require a license that includes AI Gateway.

Refer to [Spend management](./spend-management.md) for details.

### Turn and payload limits

These deployment-wide limits apply to every chat.
The defaults suit most deployments, and you can change any of them with a server flag, environment variable, or YAML key.
Each value must be at least 1, and the server fails to start if a value is 0 or negative:

| Limit                                                         | Default      | Setting                                                                                                                           |
|---------------------------------------------------------------|--------------|-----------------------------------------------------------------------------------------------------------------------------------|
| Steps (model responses) per chat turn                         | 1200         | [`CODER_CHAT_MAX_STEPS_PER_TURN`](../../../admin/setup/configuration-reference.md#max-steps-per-turn)                             |
| Consecutive retries after a failed model generation           | 25           | [`CODER_CHAT_MAX_GENERATION_RETRIES`](../../../admin/setup/configuration-reference.md#max-generation-retries)                     |
| Queued messages per chat                                      | 20           | [`CODER_CHAT_MAX_QUEUED_MESSAGES_PER_CHAT`](../../../admin/setup/configuration-reference.md#max-queued-messages-per-chat)         |
| Files linked to a chat                                        | 50           | [`CODER_CHAT_MAX_ATTACHMENTS_PER_CHAT`](../../../admin/setup/configuration-reference.md#max-attachments-per-chat)                 |
| System prompt, plan mode instructions, and custom prompt size | 128&nbsp;KiB | [`CODER_CHAT_MAX_PROMPT_BYTES`](../../../admin/setup/configuration-reference.md#max-prompt-bytes)                                 |
| Concurrent virtual desktop recording uploads per server       | 25           | [`CODER_CHAT_MAX_CONCURRENT_RECORDING_UPLOADS`](../../../admin/setup/configuration-reference.md#max-concurrent-recording-uploads) |

The concurrent agent pools described above are licensing limits, not deployment settings.

### Git providers

Coder Agents leverages your existing
[external authentication](../../../admin/external-auth/index.md) configuration
to power the in-chat diff viewer. Self-hosted GitHub Enterprise deployments
require additional configuration for this feature.

See [Git Providers](./git-providers.md) for details.

### Data retention

Administrators can configure a retention period for archived conversations.
When enabled, archived conversations and orphaned files older than the retention period are automatically purged.
The default is 30&nbsp;days.

This setting is available under **Admin settings** > **AI** > **Coder Agents** > **Lifecycle**.
Refer to [Data Retention](./chat-retention.md) for details.

### Experiments

Administrators enable experimental features using the `--experiments` flag on
`coder server` (or the `CODER_EXPERIMENTS` environment variable). Once enabled,
runtime configuration for those features is available under **Admin settings** >
**AI** > **Coder Agents**.

See the following pages for experiment-gated features:

- [Advisor](./advisor.md) (`--experiments=chat-advisor`)
- [Virtual desktop](./virtual-desktop.md) (`--experiments=chat-virtual-desktop`)
- [Inline MCP servers](./mcp-servers.md#inline-mcp-servers-experimental) (`--experiments=chat-inline-mcp-servers`)

For chat debug logging (not experiment-gated), see [Chat debug logging](./chat-debug-logging.md).

## Where we are headed

The controls above cover providers, models, system prompts, templates, MCP servers, AI Gateway budgets, and data retention.
We are continuing to invest in platform controls based on what feedback we get from customers deploying agents in regulated and enterprise environments.

### Infrastructure-level enforcement

We believe that security-critical behaviors should not depend on the system
prompt. A system prompt can instruct an agent to "always format branch names like... ," but there is no guarantee the agent will comply every time.

For controls that matter — network boundaries, git push targets, allowed
hostnames — we intend to enforce them at the infrastructure and network layer.
Examples of what this looks like:

- **Network-restricted templates for agent workloads.** Because the AI comes
  from the control plane, agent workspaces do not need outbound access to LLM
  providers. You can create templates that only permit access to your git
  provider and nothing else.

## Why we take this approach

The common pattern in the industry today is that each developer installs and
configures their own coding agent inside their development environment. This
creates several problems for platform teams:

- **No standardization.** Different developers use different agents with
  different configurations. There is no unified way to enforce conventions or
  improve the experience across the organization.
- **Security is ad-hoc.** If the agent runs inside the workspace, it has access
  to whatever the workspace has access to — API keys, network endpoints,
  credentials. Restricting this requires per-workspace configuration that is
  difficult to maintain at scale.
- **Feedback is anecdotal.** Without centralized analytics, platform teams have
  no way to know which models perform best, which prompts cause failures, or how
  much agents are costing the organization.
- **Configuration is a developer burden.** Developers — especially those who
  are not power users — should not need to think about which agent to install,
  which API key to use, or how to configure a system prompt. They should
  describe the work they want done.

As models improve and the differences between agent harnesses continue to
shrink, we believe the leverage shifts toward user experience and platform-level controls: which
models to offer, how to enforce security, and how to use analytics to
continuously improve the development experience across the organization.

---

# Template Optimization

Source: https://coder.com/docs/ai-coder/agents/platform-controls/template-optimization

Not every chat with Coder Agents requires a workspace.
The agent provisions one when missing tools, skills, MCP integrations, or context block progress, or when it needs to work with files or run commands.

When a workspace is needed, the agent reads the available templates, selects the appropriate one based on its name and description, and provisions a workspace automatically.
Administrators can [restrict which templates the agent can use](#restrict-available-templates).

This guide covers best practices for creating templates that are discoverable
and useful to Coder Agents.

## Restrict available templates

By default, every template allows Coder Agents.
Administrators can block individual templates from the template list or from each template's settings page.

To change which templates agents can use:

1. Navigate to **Admin settings** > **AI** > **Coder Agents** > **Templates**.
2. Toggle the switch for each template.

The same control is available on each template's settings page as **Allow Coder Agents to create workspaces using this template**.

When a template does not allow agents, the agent's `list_templates`, `read_template`, and `create_workspace` tools exclude it.
The agent cannot read the template or provision workspaces from it.

The setting only affects agent-created workspaces.
Developers can still manually create workspaces from any template to which they have access.
With this setting, platform teams can apply stricter policies to agent workloads without affecting the manual workspace experience.

## Write discoverable template descriptions

The agent selects templates by reading their names and descriptions, the same metadata shown on the templates page in the Coder dashboard.
The agent's `list_templates` tool ranks matches by query relevance first, then by an affinity score that weights the developer's own recent template usage far more heavily than organization popularity.
It does not inspect the template's Terraform to understand what infrastructure is inside.
For the ranking details, refer to [list_templates](../tools/index.md#how-templates-are-ranked).

This means the template description is the single most important factor in
whether the agent picks the right template for a given task.

### What to include

A good template description tells the agent:

- What language, framework, or stack the template is for.
- Which repository or service it targets, if applicable.
- What type of work it supports (e.g., backend services, frontend apps, data
  pipelines).

### Examples

| Description                                                                                 | Why it works                                                       |
|---------------------------------------------------------------------------------------------|--------------------------------------------------------------------|
| Python backend services for the payments repo. Includes Poetry, Python 3.12, and PostgreSQL | Specific language, repo, and toolchain                             |
| React frontend development for the customer portal. Node 20, pnpm, Storybook pre-installed  | Clear stack, named project, key tools listed                       |
| General-purpose Go development environment with Go 1.23, Docker, and common CLI tools       | Broad but descriptive — the agent can match it to Go-related tasks |
| Java microservices for the order-processing pipeline. Maven, JDK 21, Kafka client libraries | Names the service domain and build tool                            |

| Description        | Why it fails                                                            |
|--------------------|-------------------------------------------------------------------------|
| Team A template v2 | No information about what the template is for                           |
| Dev environment    | Too generic — the agent cannot distinguish this from any other template |
| k8s-prod-2024      | Internal shorthand that carries no meaning for the agent                |
| Default            | Tells the agent nothing                                                 |

> [!TIP]
> If many developers already use a template, the agent is more likely to select it, because organization popularity contributes to the affinity score that orders the shortlist.
> A well-written description on a popular template is the strongest routing signal you can provide.

### Template display names

Display names appear in the template selector and in the agent's tool output.
Use readable, descriptive names rather than slugs or internal codes. A display
name like "Python Backend (Payments)" is more useful to both humans and the
agent than `py-be-pay-v3`.

### Put routing context near the top of the README

The short `description` also appears on the dashboard templates page, so it is
intentionally limited to fewer than 128 characters. When that is not enough
room to fully describe a template for the agent, put the most important routing
context at the top of the template's `README.md` body, immediately after any
frontmatter block.

The chat agent's template listing includes a bounded README excerpt (roughly the
first 1,000 characters), and template detail includes the README (up to roughly
8,000 characters). Both are reduced to plain text: frontmatter is stripped,
link text is kept while link URLs are dropped, images and badges are dropped
entirely, and code blocks and tables are preserved as text. Use the opening
section to explain when to choose this template, what it is *not* for, and the
specific stack or services it provides.

```md
---
display_name: Kubernetes (Deployment)
description: Provision Kubernetes Deployments as Coder workspaces
tags: [kubernetes, container]
---

# Kubernetes Deployment

Kubernetes Deployment workspaces are for container-native development on an
existing cluster. Use this template when the work should run as a pod with
cluster access and configurable CPU, memory, and persistent storage. It is not
intended for standalone VM or local Docker workflows.
```

The README is stored with the template version when you run
`coder templates push`, so updating it is part of your normal template
workflow. The short `description` still drives the initial template listing, so
keep it accurate and specific as well.

## Create dedicated agent templates

Rather than reusing your standard interactive developer templates for agent
workloads, consider creating dedicated templates with configurations
appropriate for unattended, agent-driven work.

Agent templates differ from developer templates in several ways:

- **No IDE tooling needed.** The agent connects via the workspace daemon's HTTP
  API, not through VS Code or JetBrains. You can omit IDE-specific
  configuration, extensions, and desktop tools.
- **Stricter network policies.** Agent workspaces typically need access to only
  the control plane and your git provider. You can apply tighter egress rules
  than you would for a developer who needs to browse documentation or access
  additional services.
- **Reduced permissions.** Agent workspaces can use scoped credentials with
  fewer permissions than a developer's interactive session.

See [Creating templates](../../../admin/templates/creating-templates.md) for
step-by-step instructions on creating templates via the UI, CLI, or CI/CD.

## Configure network boundaries

The workspace is the network boundary for the agent. If you want to control
what the agent can access, control what the workspace can access.

This is a deliberate architectural advantage of running the agent loop in the
control plane. Because all AI functionality — LLM inference, tool dispatch,
chat state — lives in the control plane, agent workspaces do not need outbound
access to any LLM provider. The workspace only needs to reach:

- **The Coder control plane** — required for the workspace daemon to function.
- **Your git provider** — required for push and pull operations.

Everything else can be blocked at the network level.

### Why network boundaries are more effective than process-level controls

Traditional approaches to restricting agent behavior — such as blocking
specific commands at the process level — are difficult to enforce reliably. An
agent executing arbitrary shell commands can find alternative paths to achieve
the same result (aliasing commands, writing scripts, using different tools).

Network-level boundaries are more robust because they operate below the process
layer. If the workspace cannot reach an external service, it does not matter
what command the agent runs — the connection simply fails. This provides a
firmer security guarantee than trying to restrict individual process behaviors.

See [Architecture](../architecture.md#workspaces-can-be-fully-network-isolated)
for more detail on the security model.

## Scope permissions and credentials

> [!WARNING]
> By default, agent workspaces inherit the same network access and
> permissions as any workspace the user creates manually. If your templates
> do not explicitly restrict outbound network access, the agent has full
> internet access from the workspace. Review the guidance below and in
> [Configure network boundaries](#configure-network-boundaries) to lock
> down agent workloads appropriately.

The agent operates with the same identity and permissions as the user who
submitted the prompt. There is no privilege escalation — if a developer cannot
access a resource through the Coder dashboard, the agent cannot access it
either.

### External service credentials

When agent workspaces need access to external services (git providers, package
registries, artifact stores), configure credentials with the minimum scope
required:

- **Use separate tokens for agent templates.** Rather than sharing the same
  broad-scope token used by developer workspaces, create a dedicated token with
  only the permissions the agent needs (e.g., read/write access to specific
  repositories, no admin access).
- **Configure external auth at the template level.** Use Coder's
  [external authentication](../../../admin/external-auth/index.md) to provide scoped
  git credentials. The agent uses the same external auth flow as any other
  workspace, so credentials are managed centrally.
- **Avoid injecting long-lived secrets.** Prefer short-lived tokens or
  credential helpers over static API keys baked into the template image.

### Git identity

Every git operation the agent performs — commits, pushes, pull requests — is
attributed to the user who submitted the prompt. This happens through the
existing git authentication configured in your Coder deployment. There is no
shared bot account.

Ensure your templates configure git with the appropriate author information so
that commits are properly attributed. The agent does not override git
configuration — it uses whatever is set in the workspace environment.

## Design template parameters for automation

The agent can read template parameters — including their names, descriptions,
and defaults — and fill them in when creating a workspace. Well-designed
parameters help the agent provision the right infrastructure without human
intervention.

### Keep parameters simple

- **Use sensible defaults.** The agent performs best when most parameters have
  reasonable defaults and only a few require explicit selection. A template
  with ten required parameters and no defaults forces the agent to guess.
- **Minimize required parameters.** If a parameter is not essential for the
  agent's use case, give it a default value or make it optional.

### Write descriptive parameter metadata

The agent reads `display_name` and `description` fields to understand what a
parameter controls. Treat these the same way you treat template descriptions —
be specific and use natural language.

```tf
data "coder_parameter" "region" {
  name         = "region"
  display_name = "Deployment Region"
  type         = "string"
  description  = "AWS region for the workspace. Use us-east-1 for the payments service or eu-west-1 for GDPR-regulated workloads."
  default      = "us-east-1"
}
```

A description like "AWS region" is less useful to the agent than one that
explains when to use each option.

### Avoid opaque identifiers

Parameters with values like `ami-0abcdef1234567890` or `subnet-12345` are
difficult for the agent to reason about. Where possible, use human-readable
option labels or map opaque IDs to descriptive names using Terraform locals.

For full parameter reference — including types, validation, mutability, and
workspace presets — see
[Parameters](../../../admin/templates/extending-templates/parameters.md).
[Dynamic parameters](../../../admin/templates/extending-templates/dynamic-parameters.md)
add conditional form controls and identity-aware defaults for more advanced
use cases.

## Pre-install tools and dependencies

Agent workspaces should be ready to work immediately after provisioning. The
agent does not know how to install your organization's specific toolchain, and
time spent installing dependencies is time not spent on the task.

### What to pre-install

- **Language runtimes and build tools** for the target stack (e.g., Go, Node,
  Python, Maven).
- **Common CLI tools** the agent is likely to use: `git`, `curl`, `jq`, `make`,
  `docker` (if applicable).
- **Project-specific dependencies.** If the template targets a specific
  repository, consider pre-installing the project's dependencies or running the
  setup script as part of workspace startup.
- **Git configuration.** Ensure `git` is configured with credentials and author
  information so the agent can commit and push without additional setup.

For guidance on building and maintaining workspace images, see
[Image management](../../../admin/templates/managing-templates/image-management.md).

### Set a meaningful working directory

If the template targets a specific repository, pre-clone it and set the
working directory so the agent starts in the right place:

```tf
resource "coder_agent" "main" {
  os   = "linux"
  arch = "amd64"
  dir  = "/home/coder/payments-service"
}
```

This avoids a round trip where the agent needs to figure out where the code
lives before it can begin working.

## Use prebuilt workspaces to reduce provisioning time

Workspace provisioning is the primary source of latency when the agent begins a
task. Templates with complex infrastructure, large images, or lengthy startup
scripts can take minutes to provision — time where the developer is waiting
and the agent is idle.

[Prebuilt workspaces](../../../admin/templates/extending-templates/prebuilt-workspaces.md)
eliminate this delay by maintaining a pool of ready-to-use workspaces for
specific parameter presets. When the agent creates a workspace that matches a
preset, Coder assigns an already-running prebuilt workspace instead of
provisioning from scratch. The agent can begin working immediately.

## Checklist

Use this as a quick reference when creating or updating templates for Coder
Agents:

- Template has a specific, natural-language description that includes
  language, framework, and target project or service.
- README opening section provides longer routing context when the short
  description is not enough.
- Display name is readable and descriptive.
- Network egress is restricted to the control plane and git provider.
- External service credentials use minimal-scope tokens.
- Template parameters have sensible defaults and descriptive metadata.
- Language runtimes, build tools, and git are pre-installed.
- Prebuilt workspaces are configured for high-traffic presets (Premium).
- Working directory is set to the target repository (if applicable).

---

# Organization scope

Source: https://coder.com/docs/ai-coder/agents/platform-controls/organizations

Coder Agents configuration is split between deployment-wide settings and organization-scoped settings.
Deployment-wide settings apply to every chat in the deployment.
Organization-scoped settings apply only to chats that belong to that organization.

This page describes which settings belong to each scope, what an upgrade changes, and who can configure each setting.

Every deployment has at least the default organization, so the organization-scoped settings apply even when you never create a second organization.
Running more than 1 organization requires a [Premium license](../../../admin/users/organizations.md).

## What each scope owns

| Setting                         | Scope                  | Where to configure                                                         |
|---------------------------------|------------------------|----------------------------------------------------------------------------|
| AI providers and credentials    | Deployment             | **Admin settings** > **AI** > **Providers**                                |
| Chat models                     | Organization           | **Admin settings** > **AI** > **Models**                                   |
| Default model                   | Organization           | **Admin settings** > **AI** > **Coder Agents** > **Organization settings** |
| Admin model overrides           | Organization           | **Admin settings** > **AI** > **Coder Agents** > **Organization settings** |
| Personal model overrides        | User, per organization | **Agents** > **Settings** > **Agents**                                     |
| Personal override toggle        | Deployment             | **Admin settings** > **AI** > **Coder Agents** > **Deployment settings**   |
| MCP servers                     | Organization           | **Admin settings** > **AI** > **Coder Agents** > **MCP servers**           |
| System prompt                   | Deployment             | **Admin settings** > **AI** > **Coder Agents** > **Instructions**          |
| Plan mode instructions          | Deployment             | **Admin settings** > **AI** > **Coder Agents** > **Instructions**          |
| Agent access to a template      | Template               | **Admin settings** > **AI** > **Coder Agents** > **Templates**             |
| Advisor runtime limits          | Deployment             | **Admin settings** > **AI** > **Coder Agents** > **Deployment settings**   |
| Virtual desktop provider        | Deployment             | **Admin settings** > **AI** > **Coder Agents** > **Deployment settings**   |
| Autostop fallback and lifecycle | Deployment             | **Admin settings** > **AI** > **Coder Agents** > **Lifecycle**             |
| Data retention                  | Deployment             | **Admin settings** > **AI** > **Coder Agents** > **Lifecycle**             |

The **Deployment settings** section holds the Advisor card and the Virtual desktop card.
Both cards appear on the **Coder Agents** page.

### AI providers stay deployment-wide

An AI provider holds the upstream endpoint and the credentials, so it stays a deployment-wide resource.
A chat model belongs to 1 organization and references 1 provider.
You select a provider when you add a model, but the dashboard never shows the provider's credentials.

Refer to [Models](../models.md) for provider setup and model options.

## What an upgrade does

When a deployment upgrades to a release that scopes models and MCP servers to organizations, Coder moves the existing configuration:

- Every existing chat model moves to the default organization.
- Every existing MCP server moves to the default organization, with its credentials intact.
- Every moved model and MCP server stays available to the default organization's **Everyone** group, so current members keep access.
- The previous default model becomes the default model of the default organization.
- Coder removes the existing admin and personal model overrides.
- Coder ignores the previous Advisor model override, so you must set it again.
- The deployment-wide template allowlist becomes the per-template **Allow Coder Agents to create workspaces using this template** setting.

Other organizations start with no models and no MCP servers.
Coder copies nothing from the default organization.

> [!IMPORTANT]
> Coder does not migrate the model overrides.
> Administrators must set the organization overrides again in the **Organization settings** section of **Admin settings** > **AI** > **Coder Agents**.
> Users must set their personal overrides again in **Agents** > **Settings** > **Agents**.

The template allowlist conversion follows these rules:

- A non-empty allowlist allows only the templates it lists, and blocks every other existing template.
- A missing or empty allowlist leaves every template allowed.
- An unreadable allowlist blocks every template, so review the template list after the upgrade.

The upgrade removes the stored allowlist, so you cannot recover the original list.
Templates created after the upgrade allow agents by default.

## Organizations without models or MCP servers

A new organization has no chat models and no MCP servers.
Add at least 1 model before members start a chat in that organization.

When an organization has no model that the user can use, Coder does not start the chat.
The user sees a message that asks an administrator to configure a chat model.

An organization with no MCP servers produces no error.
Chats in that organization offer no MCP servers.

## Who configures each scope

- Deployment administrators configure the providers and every setting in the **Deployment settings** section.
- Users with edit access to an organization's models configure that organization's models and admin model overrides.
- Users with read access to an organization's models can open the **Models** page and the **Coder Agents** page, and Coder shows the fields as read-only.
- Users with access to an organization's MCP servers can open the **MCP servers** page.
- Auditors and custom roles can hold read access without edit access.

The dashboard shows the organization picker when you can access more than 1 organization.
Your access applies to the selected organization, so your controls can differ between organizations.

## Manage model and MCP server access

Each chat model and each MCP server has an access list of groups and users.
An entry lets a member use the model or the server.
Coder adds the organization's **Everyone** group when you create a model or a server, so all members have access by default.
You can add only the members and the groups of the organization that owns the model or the server.

To change a model's access list, open **Model actions** > **Manage permissions** on the **Models** page.
Refer to [Manage model permissions](../models.md#manage-model-permissions) for the steps.

To change an MCP server's access list, open **Server actions** >
**Manage permissions** on the **MCP servers** page. Refer to
[Access control](./mcp-servers.md#access-control) for details.

You can also use the API:

- `GET /api/v2/organizations/{organization}/mcp-servers/{mcpserverconfig}/acl`
- `PATCH /api/v2/organizations/{organization}/mcp-servers/{mcpserverconfig}/acl`

## Related pages

- [Models](../models.md) for providers, models, and model overrides.
- [MCP Servers](./mcp-servers.md) for MCP server configuration.
- [Template Optimization](./template-optimization.md) for the per-template agent setting.

---

# Network isolation

Source: https://coder.com/docs/ai-coder/agents/platform-controls/agent-isolation

Use your template to run the AI agent in a separate sandbox from the user's development environment.
You control which files and networks the agent can access without restricting the user's access.

This guide uses Kubernetes, but you can use another sandbox, such as Bubblewrap with firewall rules.
Coder selects the workspace agent that runs chat tools.
You configure the sandbox around that agent.

> [!NOTE]
> Sandboxing in Coder is at an early stage and is subject to change.
> [Contact us](https://coder.com/contact) to share feedback.

## How it works

- The user's Pod keeps its normal development access.
- The AI agent's Pod runs as a non-root user with a network policy that allows Coder.
- Both Pods share project files, but have separate home directories.

Network policies select Pods, not individual containers.
Use separate Pods to give the user and AI agent different network access.
The Pods run on the same node and share one `ReadWriteOnce` persistent volume claim (PVC).
They do not need `ReadWriteMany` storage.

## 1. Configure the template

Use a test namespace and a workspace without sensitive data.
You need:

- A Linux cluster with NetworkPolicy enforcement turned on for standalone Pods.
- A default storage class that provides a volume writable by user and group ID `1000`.
- A fixed IPv4 address and TCP port for Coder, including agent downloads and relay connections.
- A Coder provisioner with permission to create Pods, a PVC, a ConfigMap, and a NetworkPolicy in that namespace.

Check these permissions using the provisioner's Kubernetes credentials:

```sh
kubectl auth can-i create pods -n YOUR_NAMESPACE
kubectl auth can-i create persistentvolumeclaims -n YOUR_NAMESPACE
kubectl auth can-i create configmaps -n YOUR_NAMESPACE
kubectl auth can-i create networkpolicies.networking.k8s.io -n YOUR_NAMESPACE
```

Each command must return `yes`.
The provisioner also needs permission to read, update, and delete these resources.

> [!WARNING]
> Do not run untrusted code until the network tests pass.
> Kubernetes can accept a NetworkPolicy without enforcing it, leaving the agent's network access unrestricted.

For GKE, check [network policy enforcement](https://cloud.google.com/kubernetes-engine/docs/how-to/network-policy).
For Amazon VPC CNI, use Deployment-managed Pods instead of this example's standalone Pods.
[AWS documents unreliable enforcement for standalone Pods](https://docs.aws.amazon.com/eks/latest/userguide/cni-network-policy.html).

Save this Terraform as `main.tf` in an empty template directory.
Edit the `locals` block at the top of the file with your namespace and Coder server address.

<details>
<summary>main.tf: two Pods, one project volume, and an agent network policy</summary>

```tf
terraform {
  required_providers {
    coder      = { source = "coder/coder" }
    kubernetes = { source = "hashicorp/kubernetes" }
  }
}

locals {
  # Edit these values for your cluster and Coder deployment.

  # Use ~/.kube/config on the provisioner host instead of in-cluster authentication.
  use_kubeconfig = false
  # Existing namespace for workspace resources.
  namespace = "coder-sandbox-test"
  # Storage class for the shared project PVC. Null uses the cluster default.
  storage_class_name = null
  # Hostname in the Coder access URL, without scheme or port.
  coder_host = "coder.example.com"
  # Trusted fixed IPv4 address of the external Coder endpoint, not a cluster Service or node IP.
  coder_ip = "192.0.2.10"
  # TCP port of the Coder endpoint (including agent downloads and embedded DERP).
  coder_port = 443
}

provider "kubernetes" {
  config_path = local.use_kubeconfig ? "~/.kube/config" : null
}

data "coder_workspace" "me" {}
data "coder_provisioner" "me" {}

resource "coder_agent" "dev" {
  os   = "linux"
  arch = data.coder_provisioner.me.arch
  dir  = "/home/coder/project"
}
resource "coder_agent" "dev-coderd-chat" {
  os   = "linux"
  arch = data.coder_provisioner.me.arch
  dir  = "/home/coder/project"
  env  = { CODER_AGENT_EXP_MCP_CONFIG_FILES = "/etc/coder/mcp.json" }
}

locals {
  name   = "coder-${data.coder_workspace.me.id}"
  labels = { "com.coder.workspace.id" = data.coder_workspace.me.id }
}

resource "kubernetes_persistent_volume_claim_v1" "project" {
  metadata {
    name      = "${local.name}-project"
    namespace = local.namespace
  }
  wait_until_bound = false
  spec {
    access_modes       = ["ReadWriteOnce"]
    storage_class_name = local.storage_class_name
    resources {
      requests = { storage = "10Gi" }
    }
  }
}

resource "kubernetes_config_map_v1" "mcp" {
  metadata {
    name      = "${local.name}-mcp"
    namespace = local.namespace
  }
  data = { "mcp.json" = jsonencode({ mcpServers = {} }) }
}

resource "kubernetes_network_policy_v1" "sandbox" {
  metadata {
    name      = "${local.name}-sandbox"
    namespace = local.namespace
  }
  spec {
    pod_selector {
      match_labels = merge(local.labels, { "coder.com/agent-role" = "sandbox" })
    }
    policy_types = ["Egress"]
    egress {
      to {
        ip_block {
          cidr = "${local.coder_ip}/32"
        }
      }
      ports {
        protocol = "TCP"
        port     = local.coder_port
      }
    }
  }
}

resource "kubernetes_pod_v1" "dev" {
  count = data.coder_workspace.me.start_count
  metadata {
    name      = "${local.name}-dev"
    namespace = local.namespace
    labels    = merge(local.labels, { "coder.com/agent-role" = "dev" })
  }
  spec {
    automount_service_account_token = false
    host_network                    = false
    security_context {
      run_as_user     = 1000
      run_as_group    = 1000
      fs_group        = 1000
      run_as_non_root = true
      seccomp_profile { type = "RuntimeDefault" }
    }
    host_aliases {
      ip        = local.coder_ip
      hostnames = [local.coder_host]
    }
    container {
      name        = "dev"
      image       = "codercom/example-base:ubuntu"
      command     = ["sh", "-c", coder_agent.dev.init_script]
      working_dir = "/home/coder/project"
      env {
        name  = "CODER_AGENT_TOKEN"
        value = coder_agent.dev.token
      }
      volume_mount {
        name       = "home"
        mount_path = "/home/coder"
      }
      volume_mount {
        name       = "project"
        mount_path = "/home/coder/project"
      }
      volume_mount {
        name       = "tmp"
        mount_path = "/tmp"
      }
    }
    volume {
      name = "project"
      persistent_volume_claim {
        claim_name = kubernetes_persistent_volume_claim_v1.project.metadata[0].name
      }
    }
    volume {
      name = "home"
      empty_dir {}
    }
    volume {
      name = "tmp"
      empty_dir {}
    }
  }
}

resource "kubernetes_pod_v1" "sandbox" {
  count      = data.coder_workspace.me.start_count
  depends_on = [kubernetes_network_policy_v1.sandbox]
  metadata {
    name      = "${local.name}-dev-coderd-chat"
    namespace = local.namespace
    labels    = merge(local.labels, { "coder.com/agent-role" = "sandbox" })
  }
  spec {
    automount_service_account_token = false
    host_network                    = false
    security_context {
      run_as_user     = 1000
      run_as_group    = 1000
      fs_group        = 1000
      run_as_non_root = true
      seccomp_profile {
        type = "RuntimeDefault"
      }
    }
    # Dev schedules independently, including with WaitForFirstConsumer storage.
    affinity {
      pod_affinity {
        required_during_scheduling_ignored_during_execution {
          topology_key = "kubernetes.io/hostname"
          label_selector {
            match_labels = merge(local.labels, { "coder.com/agent-role" = "dev" })
          }
        }
      }
    }
    host_aliases {
      ip        = local.coder_ip
      hostnames = [local.coder_host]
    }
    container {
      name        = "dev-coderd-chat"
      image       = "codercom/example-base:ubuntu"
      command     = ["sh", "-c", coder_agent.dev-coderd-chat.init_script]
      working_dir = "/home/coder/project"
      env {
        name  = "CODER_AGENT_TOKEN"
        value = coder_agent.dev-coderd-chat.token
      }
      env {
        name  = "CODER_AGENT_EXP_MCP_CONFIG_FILES"
        value = "/etc/coder/mcp.json"
      }
      security_context {
        allow_privilege_escalation = false
        read_only_root_filesystem  = true
        run_as_non_root            = true
        capabilities { drop = ["ALL"] }
      }
      volume_mount {
        name       = "home"
        mount_path = "/home/coder"
      }
      volume_mount {
        name       = "project"
        mount_path = "/home/coder/project"
      }
      volume_mount {
        name       = "tmp"
        mount_path = "/tmp"
      }
      volume_mount {
        name       = "mcp"
        mount_path = "/etc/coder"
        read_only  = true
      }
    }
    volume {
      name = "project"
      persistent_volume_claim {
        claim_name = kubernetes_persistent_volume_claim_v1.project.metadata[0].name
      }
    }
    volume {
      name = "home"
      empty_dir {}
    }
    volume {
      name = "tmp"
      empty_dir {}
    }
    volume {
      name = "mcp"
      config_map {
        name = kubernetes_config_map_v1.mcp.metadata[0].name
      }
    }
  }
}
```

</details>

Use the Coder hostname without `https://` or a port.
Use an external IP address, not a cluster Service or node IP.
`hostAliases` lets the agent find Coder at this IP without DNS.
If your cluster has no default storage class, set `storage_class_name` to one that fits the requirements above.

If the provisioner runs outside the cluster, set `use_kubeconfig = true`.
Provide `~/.kube/config` on the provisioner host.
Otherwise, the example uses in-cluster authentication.

The AI agent runs as user ID `1000`, without Linux capabilities or a Kubernetes service-account token.
It can write to its home, temporary directories, and shared project, but not system files.
It uses the runtime's default security profile.

The network policy allows Coder's IP and TCP port, but not DNS.
Coder selects the agent whose name ends in `-coderd-chat`.
Use this ending on exactly one top-level agent.

## 2. Create a workspace

Sign in to Coder.
From the template directory, run:

```sh
terraform init
terraform validate
coder templates push sandbox-k8s --directory .
coder create sandbox-test --template sandbox-k8s
```

After the template passes validation, wait for both agents to connect.
In **Agents**, start a chat attached to `sandbox-test`.
Ask the chat to run:

```sh
id -u
touch /home/coder/project/sandbox-check
touch /etc/sandbox-check
```

The first command must print `1000`.
The agent must create the project file but fail to write to `/etc`.
Read each command's output, not only the chat summary.

## 3. Test network access

Try GitHub and the npm registry from the user's terminal:

```sh
curl --noproxy '*' --head --max-time 10 https://github.com
curl --noproxy '*' --head --max-time 10 https://registry.npmjs.org
```

Both requests must return HTTP headers.
Then ask the chat to run the same commands.
Both must fail with a DNS error, a connection error, or a timeout.
The chat must still be able to run commands through Coder.

A DNS error does not prove that the policy blocks connections to IP addresses.
Find GitHub's IP address from the user's Pod.
Repeat the request from the user's terminal and the chat with that address:

```sh
# Run in the user's Pod.
getent ahostsv4 github.com

# Replace GITHUB_IP with an address from that output. Run in both Pods.
curl --noproxy '*' --head --max-time 10 --resolve github.com:443:GITHUB_IP https://github.com
```

The user's request must succeed, and the agent's request must fail to connect.
If the agent reaches either site, stop the test workspace.
Fix policy enforcement before continuing.

To test PostgreSQL, use a test database you control.
Run `SELECT 1` from the user's terminal.
Ask the chat to run the same query.
The user's request must succeed.
The agent's request must fail to connect.
A login error does not count as a blocked connection.

If the user cannot reach GitHub or npm, fix that connection before testing the agent.

## Limits

Other NetworkPolicies can allow connections that this policy blocks.
Your network plugin can also allow traffic to the node or its local DNS service.
Review these exceptions in the [Kubernetes NetworkPolicy documentation](https://kubernetes.io/docs/concepts/services-networking/network-policies/).

The agent can read any credentials you give it, edit shared files, and send data to Coder.
Keep workspace MCP configuration outside the shared project.
This policy does not restrict organization MCP servers.
Restrict their tools and credentials separately.

If you use another sandbox, apply it to the full workspace agent and its child processes.
Restricting only a shell leaves file tools and workspace MCP processes outside the sandbox.

---

# MCP Servers

Source: https://coder.com/docs/ai-coder/agents/platform-controls/mcp-servers

Organization admins can register external MCP servers that provide additional
tools for agent chat sessions. Each organization has its own set of MCP
servers, and chats only offer servers from the chat's organization. Configured
servers are injected into or offered to users during chat depending on the
availability policy.

This feature is accessible at **Admin settings** > **AI** > **Coder Agents** > **MCP servers**
(`/ai/settings/mcp-servers`). In multi-organization deployments, use the
organization picker to choose which organization's servers to manage. The
server list shows the picker when you can access more than one organization's
servers. The add and update views always show the target organization, as a
read-only field when only one organization is available.

## Add an MCP server

1. Navigate to **Admin settings** > **AI** > **Coder Agents** > **MCP servers**.
1. Select **Add server**.
1. Fill in the configuration fields described below.
1. Select **Save**.

### Identity

| Field          | Required | Description                                                                                       |
|----------------|----------|---------------------------------------------------------------------------------------------------|
| `display_name` | Yes      | Human-readable name shown to users in chat.                                                       |
| `slug`         | Yes      | URL-safe identifier, auto-generated from display name. It must be unique within the organization. |
| `description`  | No       | Brief summary of what the server provides.                                                        |
| `icon_url`     | No       | Emoji or image URL displayed alongside the server name.                                           |

### Connection

| Field       | Required | Description                                     |
|-------------|----------|-------------------------------------------------|
| `url`       | Yes      | The MCP server endpoint URL.                    |
| `transport` | Yes      | Transport protocol. `streamable_http` or `sse`. |

### Availability

| Field                   | Required | Description                                                                                                                         |
|-------------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------|
| `enabled`               | No       | Master toggle. Disabled servers are hidden from non-admin users.                                                                    |
| `availability`          | Yes      | Controls how the server appears in chat sessions. See [Availability policies](#availability-policies).                              |
| `model_intent`          | No       | When enabled, requires the model to describe each tool call's purpose in natural language, shown as a status label in the UI.       |
| `forward_coder_headers` | No       | When enabled, forwards Coder identity headers on every outgoing MCP request. See [Coder identity headers](#coder-identity-headers). |

#### Availability policies

| Policy        | Behavior                                                                          |
|---------------|-----------------------------------------------------------------------------------|
| `force_on`    | Injected into every chat whose owner has ACL access to the server. No opting out. |
| `default_on`  | Pre-selected in new chats. Users can opt out.                                     |
| `default_off` | Available in the server list but users must opt in.                               |

## Authentication

Each MCP server uses one of five authentication modes. When you change the
auth type, fields from the previous type are automatically cleared.

OAuth2 client secrets, API keys, and custom headers are never returned in API responses.
Boolean flags indicate whether each value is set.

### None

No credentials are sent. Use this for servers that do not require
authentication.

### OAuth2

Per-user authorization. The administrator configures the OAuth2 provider, and
each user independently completes the authorization flow.

**Manual configuration** — provide all three fields together:

| Field              | Description                 |
|--------------------|-----------------------------|
| `oauth2_client_id` | OAuth2 client ID.           |
| `oauth2_auth_url`  | Authorization endpoint URL. |
| `oauth2_token_url` | Token endpoint URL.         |

Optional fields:

| Field                   | Description                               |
|-------------------------|-------------------------------------------|
| `oauth2_client_secret`  | OAuth2 client secret.                     |
| `oauth2_scopes`         | Space-separated list of scopes.           |
| `oauth2_revocation_url` | Token revocation endpoint URL (RFC 7009). |

The revocation endpoint must use HTTPS.
Loopback URLs may use HTTP for local development and tests.

**Auto-discovery** — leave `oauth2_client_id`, `oauth2_auth_url`, and
`oauth2_token_url` empty. The server attempts discovery in this order:

1. RFC 9728 — Protected Resource Metadata
1. RFC 8414 — Authorization Server Metadata
1. RFC 7591 — Dynamic Client Registration

Auto-discovery also records the provider's `revocation_endpoint` from the
RFC 8414 metadata when advertised. An explicit `oauth2_revocation_url` in
the request takes precedence over the discovered value.

Users connect through a popup that redirects through the OAuth2 provider.
Tokens are stored per-user and refreshed automatically. Users can disconnect
via the UI or API to remove stored tokens. When a revocation endpoint is
configured, disconnecting also asks the provider to revoke the token
(RFC 7009). Provider revocation is best-effort: the stored token is always
deleted from Coder, and the disconnect response reports whether provider
revocation succeeded via `token_revoked` and `token_revocation_error`.

### API key

A static key sent as a header on every request.

| Field            | Required | Description                          |
|------------------|----------|--------------------------------------|
| `api_key_header` | Yes      | Header name (e.g., `Authorization`). |
| `api_key_value`  | Yes      | Secret value sent in the header.     |

### Custom headers

Arbitrary key-value header pairs sent on every request. At least one header
is required when this mode is selected.

### User OIDC Identity

Forwards the calling user's OIDC access token (stored in
`user_links.oauth_access_token`) to the MCP server as an
`Authorization: Bearer <token>` header. The token is refreshed
transparently before each request if it has expired or is close to
expiring.

No admin-configurable fields. No per-user connect step.

**Limitation**: this auth mode only works for users who authenticated to
Coder via OIDC. Users who logged in with password or GitHub will see
requests sent without an authorization header, and the upstream MCP
server is expected to respond with 401.

## Tool governance

Control which tools from a server are available in chat:

| Field             | Description                                                                           |
|-------------------|---------------------------------------------------------------------------------------|
| `tool_allow_list` | If non-empty, only the listed tool names are exposed. An empty list allows all tools. |
| `tool_deny_list`  | Listed tool names are always blocked, even if they appear in the allow list.          |

## Coder identity headers

MCP servers configured with `forward_coder_headers = true` receive Coder identity headers on every outgoing request.
When the server config has a signing secret, Coder also signs the request body and the effective identity header values.

| Header                        | Description                                                                               |
|-------------------------------|-------------------------------------------------------------------------------------------|
| `X-Coder-Owner-Id`            | Coder user who owns the chat that issued the tool call.                                   |
| `X-Coder-Chat-Id`             | Top-level parent chat ID. For root chats, this is the chat's own ID.                      |
| `X-Coder-Subchat-Id`          | Subchat ID. This header is absent for root chats.                                         |
| `X-Coder-Workspace-Id`        | Workspace associated with the chat. This header is absent when the chat has no workspace. |
| `X-Coder-Signature-Timestamp` | Unix timestamp in seconds used to limit replay.                                           |
| `X-Coder-Signature`           | Request signature in the form `v1=<lowercase hexadecimal HMAC-SHA256>`.                   |

Coder sends the same identity headers to LLM providers, so a first-party MCP server can correlate a tool call with the originating chat.

### Configure request signing

Enable **Forward Coder identity headers** and enter a **Signing secret** under **Behavior**.
Generate a strong random secret, for example with `openssl rand -hex 32`, and configure the same secret on the MCP server.
Use the hexadecimal text as the HMAC key, not the decoded bytes.
Without a secret, forwarding remains unsigned.

The existing create and update APIs accept `signing_secret`.
Coder never returns it; responses expose only `has_signing_secret`.
Omitting it in an update preserves the stored value; an explicit empty string clears it.
In the UI, leaving the secret field unchanged or blank preserves the existing secret.

> [!WARNING]
> Coordinate secret changes with the MCP server.
> Requests fail verification when Coder and the MCP server use different secrets.

### Signature format

Coder builds this canonical string from the outgoing request.
The lines use `\n` separators with no trailing newline:

```txt
v1
<timestamp from X-Coder-Signature-Timestamp>
<HTTP method, uppercase>
<request path including query, for example /api/mcp?x=1>
<lowercase hexadecimal SHA-256 of the exact request body bytes>
owner=<value of X-Coder-Owner-Id>
chat=<value of X-Coder-Chat-Id>
subchat=<value of X-Coder-Subchat-Id>
workspace=<value of X-Coder-Workspace-Id>
```

An absent identity header contributes an empty value after the equals sign.
A request without a body uses the SHA-256 hash of the empty byte string.
Coder sets `X-Coder-Signature` to `v1=` followed by the lowercase hexadecimal HMAC-SHA256 of the canonical string, keyed with the server's signing secret.
The `v1=` prefix identifies the signing algorithm version.

If an auth header for the configured `auth_type` collides with an identity header, the auth header wins.
Coder signs the effective header value that the request sends.

### Verify signatures

The receiver must hash the raw request body before JSON parsing or other transformations.
Use the raw request target, including its leading slash and query string, in the canonical string.
Receivers MUST use constant-time comparison for the signature.
Receivers MUST treat the identity headers as trustworthy only after signature verification succeeds.
Reject requests when the timestamp differs from the receiver's current time by more than 300&nbsp;seconds.
This timestamp window is the `v1` replay bound because `v1` has no nonce or replay cache.

Because the identity headers disclose chat identity, **Forward Coder identity headers** is off by default.
Enable it only for first-party or trusted internal MCP servers.

## Permissions

| Action                    | Required role              |
|---------------------------|----------------------------|
| Create, update, or delete | Organization admin         |
| View enabled servers      | Member granted through ACL |
| OAuth2 connect            | Member granted through ACL |
| OAuth2 disconnect         | Token owner                |
| Manage ACLs               | Organization admin         |

Disconnect only needs a valid session: users removed from the ACL or the
organization can still delete their stored token and revoke the provider
grant.

Members only see enabled servers in their own organizations. Sensitive fields
such as API keys and client secrets are redacted in API responses.

Users with access to an organization's MCP servers can open the **MCP servers**
settings page. Coder enables the edit controls for the users who can manage the
selected organization's servers.
Only deployment administrators can add or update a server that uses **User OIDC Identity** authentication.

Refer to [Organization scope](./organizations.md) for the organization scope of MCP servers and the upgrade behavior.

### Access control

Each server has a group and user ACL that controls which members can see and
use it. New servers grant read access to the organization's **Everyone** group,
so all members have access by default. Members with MCP server share permission
can open **Server actions** > **Manage permissions** to remove the Everyone
entry and grant specific groups or users instead. They can also manage the ACL
through the API
(`GET`/`PATCH /api/v2/organizations/{organization}/mcp-servers/{id}/acl`).
ACL management is available in all editions and does not require an enterprise
entitlement. ACL changes are recorded in the audit log.

Revoking access stops a member from newly selecting the server in any chat,
but chats that already have the server selected keep using it, the same way
existing workspaces keep running after template access is revoked. To cut
off existing chats as well, disable or delete the server.

## Inline MCP servers (experimental)

> [!NOTE]
> This feature is experimental.
> Pin a release before broad rollout and review the release notes before upgrading.

### Enable the experiment

```sh
coder server --experiments=chat-inline-mcp-servers
```

Or set the environment variable:

```sh
CODER_EXPERIMENTS=chat-inline-mcp-servers
```

### What it does

A chat owner can declare up to five MCP servers inline on a chat through the API, by URL and headers, with no administrator registration.
Inline servers sit next to the organization-registered servers selected with `mcp_server_ids`.
On every turn, chatd connects to each declared server over streamable HTTP, calls `tools/list`, and offers the discovered tools to the model next to the built-in and organization-registered tools.

Declare servers on `POST /api/v2/chats`:

```json
{
  "organization_id": "...",
  "content": [{ "type": "text", "text": "Look up the order." }],
  "inline_mcp_servers": [
    {
      "slug": "orders",
      "url": "https://mcp.example.com/orders",
      "headers": { "Authorization": "Bearer ..." },
      "tool_allow_list": ["lookup_order"],
      "allow_in_subagents": false,
      "forward_coder_headers": false
    }
  ]
}
```

`POST /api/v2/chats/{chat}/messages` accepts the same field and replaces the chat's set before the turn runs.
Omit `inline_mcp_servers` to keep the current set.
Send `[]` to remove every server.
A server whose `slug` already exists keeps its `id`.
Only root chats accept `inline_mcp_servers`.
At the start of each turn, a subagent chat loads the root chat's current servers that have `allow_in_subagents` set to `true`.
A change to the root chat's set also applies to existing subagents on their next turn.
Plan mode does not limit the root chat's servers.
A subagent chat in plan mode gets none of them.

### Fields

| Field                   | Description                                                                                                                      |
|-------------------------|----------------------------------------------------------------------------------------------------------------------------------|
| `slug`                  | 1 to 32 ASCII letters, numbers, `_`, or `-`, starting with a letter or number. Unique within the chat. Prefixes every tool name. |
| `url`                   | Streamable HTTP MCP endpoint. Refer to [URL and header requirements](#url-and-header-requirements).                              |
| `headers`               | Up to 16 HTTP headers sent on every request. This is the only credential mechanism.                                              |
| `tool_allow_list`       | Same semantics as [Tool governance](#tool-governance). Up to 64 names. Cannot be combined with `tool_deny_list`.                 |
| `tool_deny_list`        | Same semantics as [Tool governance](#tool-governance). Up to 64 names. Cannot be combined with `tool_allow_list`.                |
| `allow_in_subagents`    | Offer the server's tools to subagent chats spawned from this chat. Defaults to `false`.                                          |
| `forward_coder_headers` | Send the [Coder identity headers](#coder-identity-headers). Defaults to `false`.                                                 |

### Limits

| Limit                         | Value        |
|-------------------------------|--------------|
| Servers per chat              | 5            |
| Total size of one declaration | 24&nbsp;KiB  |
| Slug                          | 32&nbsp;B    |
| URL                           | 2&nbsp;KiB   |
| Headers per server            | 16           |
| Header name                   | 128&nbsp;B   |
| Header value                  | 8&nbsp;KiB   |
| Tool names per filter list    | 64           |
| Tool name                     | 128&nbsp;B   |
| Tools per server              | 64           |
| HTTP response body            | 1&nbsp;MiB   |
| Tool result                   | 256&nbsp;KiB |
| Time per tool call            | 60&nbsp;s    |

### URL and header requirements

The URL must use `https://`, or `http://` to an IP literal inside `CODER_MCP_ALLOWED_PRIVATE_CIDRS`.
The URL must not contain userinfo, a query string, or a fragment.
Private and reserved IP literals are rejected at declaration time.
Hostnames that resolve to a blocked range fail when chatd connects.

Header names that Coder or the MCP transport control are reserved and rejected: names starting with `Proxy-` or `X-Coder-`, and `Host`, `Content-Length`, `Connection`, `Transfer-Encoding`, `Trailer`, `Upgrade`, `TE`, `Keep-Alive`, `Accept`, `Accept-Encoding`, `Content-Type`, `Last-Event-ID`, `MCP-Protocol-Version`, and `MCP-Session-ID`.

Header names are case-insensitive.
A declaration that repeats a name with different casing is rejected.

### Security

Header values are encrypted at rest when [database encryption](../../../admin/security/database-encryption.md) is configured.
The URL, each of its path segments, and header values are redacted from every string the model sees, including tool descriptions and tool results.
Each part of a header value separated by whitespace, `;`, or `,`, such as the token in `Bearer <token>`, is also redacted.
In a `name=value` part, such as `session=<token>` in a `Cookie` header, the value is also redacted on its own, but the name is not.
Parts and values shorter than 8&nbsp;bytes are not redacted.

Inline servers have no signing secret, so Coder does not sign the [Coder identity headers](#coder-identity-headers) it sends to them.
Use these headers to link requests to chats, not to authenticate the user.

Tool calls are at-least-once.
Every `tools/call` request carries `_meta["com.coder/tool_call_id"]`, which stays the same across chatd retries of one model tool call.
A server can use it to deduplicate side effects.

### Kill switch

`--disable-chat-caller-supplied-tools` (`CODER_DISABLE_CHAT_CALLER_SUPPLIED_TOOLS`) rejects chat requests that include `unsafe_dynamic_tools` or `inline_mcp_servers` with `403`, and runs existing chats without either.
The flag takes effect on `coder server` restart.
Turning off the `chat-inline-mcp-servers` experiment has the same effect on existing chats: declared servers stay stored and are not connected.
`GET /api/v2/chats/{chat}` still returns declared servers while the flag is set, and a message with `"inline_mcp_servers": []` still removes them.

### Read back

`GET /api/v2/chats/{chat}` returns the declared servers in `inline_mcp_servers` to every user who can read the chat.
The `url` field is empty unless the chat owner makes the request.
Chat list responses do not include them.
Each server includes `has_custom_headers` but never header names or values.

---

# Spend management (Premium)

Source: https://coder.com/docs/ai-coder/agents/platform-controls/spend-management

Coder controls agent spend with AI Gateway budgets, and surfaces the resulting spend to both admins and users.

## Budgets

Coder Agents spend is controlled by AI Gateway budgets, which cap all AI Gateway usage (including Coder Agents chats) per user over the budget period.

- **Group budgets**: set a budget for a group from the group's settings page.
  The deployment budget policy resolves which group budget applies when a user belongs to multiple budgeted groups, which defaults to the group with the highest budget.
- **Per-user overrides**: set a custom budget for an individual user, attributed to one of their groups.
  Per-user overrides take priority over group budgets.

The deployment flags `--ai-budget-policy` and `--ai-budget-period` currently
support only `highest` and `month`. `highest` selects the group with the
largest spend limit, and `month` resets spend at the start of each UTC
calendar month. A user who belongs to no budgeted group falls back to the
Everyone group, which has no budget unless one is set for it. There is no
deployment-wide budget amount, and a configured spend limit cannot exceed
$1,000,000 per member per period.

> [!IMPORTANT]
> Budget controls in the Coder UI, the group budget endpoints (`/api/v2/groups/{group}/ai/budget`), and the AI spend status and reporting endpoints all require the AI Gateway entitlement.
> No experiment is needed.
>
> Native chat usage limits and native cost tracking are removed from the application.
> Existing native limit values are not migrated to AI Gateway budgets and are no longer enforced.
> Configured per-model prices and historical native cost totals are also not migrated to AI Gateway.
> Before upgrading, record any per-model prices you need from **Admin settings** > **AI** > **Models**.
> The old cost endpoints default `start_date` to 30&nbsp;days before the request and `end_date` to the request time, so choose explicit RFC 3339 UTC values that cover all history you need.
> Fetch `/api/v2/chats/cost/users?start_date=<start>&end_date=<end>&limit=100&offset=0` and save the response.
> After each page, stop when `offset + users.length >= count`; otherwise, increase `offset` by 100 and fetch the next page.
> For every `users[].user_id` across those pages, save `/api/v2/chats/cost/{user_id}/summary?start_date=<start>&end_date=<end>` with the same dates.
> Each summary contains the user's totals plus `by_model` and `by_chat` breakdowns.
> After upgrading, the native **Spend** page, per-model pricing fields, and aggregate cost endpoints are unavailable.
> Historical `chat_messages.total_cost_micros` values remain in the database temporarily for rolling upgrade compatibility, but AI Gateway reports do not include or reconstruct them.
> Configure AI Gateway budgets separately.

The API reference documents how to [get](../../../reference/api/enterprise.md#get-group-ai-budget), [upsert](../../../reference/api/enterprise.md#upsert-group-ai-budget), and [delete](../../../reference/api/enterprise.md#delete-group-ai-budget) a group budget.

### Enforcement

- The AI Gateway checks the user's current spend before forwarding each request.
  When spend meets or exceeds the budget, the request is rejected and the chat shows a terminal error explaining that the budget was exceeded.
- Brief overage is possible when concurrent requests are in flight, because cost is recorded after the LLM responds.

### User-facing status

The usage indicator on the Agents page and the summary in the user menu both show the signed-in user's current AI spend, their budget, and the period reset date.
Both appear only when the deployment has the AI Gateway entitlement.

## Spend details

Spend is shown where it is actionable:

<!-- TODO(AIGOV-685): Restore once the User spend page moves out of experimental.
- **Admin settings** > **AI** > **User spend**: total and per-user AI Gateway spend for the selected organization and reporting period.
  If you can also view AI sessions, you can filter it by provider, model, and client.
-->
- **Agents page and user menu**: the signed-in user's spend against their budget, as described previously.
- **Group settings**: each member's spend against the group's budget, for admins who can manage the group.
- **Chat summary panel**: the cost of one chat tree, on a chat's Summary tab.
  A subagent reports the total for its whole tree, including the chat that started it.

For organization spend exports, refer to [AI Gateway spend export](../../ai-gateway/cost-controls.md#spend-export).

The AI Gateway [sessions views](../../ai-gateway/audit.md#navigate-the-ui) show per-request token usage, which is the input to those costs rather than the costs themselves.

AI Gateway data is subject to its own [retention period](../../ai-gateway/monitoring.md#data-retention), 60&nbsp;days by default, which is configured independently of chat retention.
Spend for requests older than that period is no longer reported, so a chat for which gateway records have been pruned reports no cost.

---

# Git Providers

Source: https://coder.com/docs/ai-coder/agents/platform-controls/git-providers

Coder Agents leverages your existing
[external authentication](../../../admin/external-auth/index.md) configuration
to power the in-chat diff viewer.
Self-hosted GitHub Enterprise deployments require one additional setting
(`API_BASE_URL`) for this feature to work.

## GitHub Enterprise configuration

For public `github.com`, no additional configuration is needed.

For self-hosted GitHub Enterprise, add `API_BASE_URL` to your
[existing configuration](../../../admin/external-auth/index.md#github-enterprise):

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-github"
CODER_EXTERNAL_AUTH_0_TYPE=github
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_AUTH_URL="https://github.example.com/login/oauth/authorize"
CODER_EXTERNAL_AUTH_0_TOKEN_URL="https://github.example.com/login/oauth/access_token"
CODER_EXTERNAL_AUTH_0_VALIDATE_URL="https://github.example.com/api/v3/user"
CODER_EXTERNAL_AUTH_0_API_BASE_URL="https://github.example.com/api/v3"
CODER_EXTERNAL_AUTH_0_REGEX=github\.example\.com
```

Without `API_BASE_URL`, Coder defaults to `https://api.github.com`. Clone
and push still work (they use `AUTH_URL` and `TOKEN_URL` directly), but
the diff viewer silently fails because Coder builds its URL-matching
patterns from the API base URL.

> [!NOTE]
> If you have both a `github.com` and a GHE external auth config, only the
> GHE config needs `API_BASE_URL`.

## GitLab configuration

For `gitlab.com`, no additional `API_BASE_URL` is needed. Coder
automatically derives it from your `AUTH_URL` for self-hosted instances.

### Required scopes

The default GitLab scopes (`read_user`) are sufficient for basic
authentication. To use merge request features (diffs, status checks) with
Coder Agents, configure:

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-gitlab"
CODER_EXTERNAL_AUTH_0_TYPE=gitlab
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_SCOPES="write_repository read_api"
```

The `read_api` scope grants read access to the API (needed for fetching
merge request metadata and diffs). The `write_repository` scope allows
pushing commits and creating merge requests.

### Self-hosted GitLab

For self-hosted GitLab, set `AUTH_URL` and `TOKEN_URL` to your instance.
Coder derives `API_BASE_URL` automatically from `AUTH_URL`:

```dotenv
CODER_EXTERNAL_AUTH_0_ID="primary-gitlab"
CODER_EXTERNAL_AUTH_0_TYPE=gitlab
CODER_EXTERNAL_AUTH_0_CLIENT_ID=xxxxxx
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=xxxxxxx
CODER_EXTERNAL_AUTH_0_AUTH_URL="https://gitlab.example.com/oauth/authorize"
CODER_EXTERNAL_AUTH_0_TOKEN_URL="https://gitlab.example.com/oauth/token"
CODER_EXTERNAL_AUTH_0_SCOPES="write_repository read_api"
CODER_EXTERNAL_AUTH_0_REGEX=gitlab\.example\.com
```

> [!NOTE]
> You may also set `API_BASE_URL` explicitly if needed (e.g.,
> `https://gitlab.example.com/api/v4`), but this is usually unnecessary.

## Known limitations

### GitLab

The GitLab provider has some semantic differences compared to the GitHub
provider:

- **Approved** uses GitLab's threshold-based approval (e.g., "all required
  approvals met") rather than GitHub's "at least one approval and no changes
  requested" model.
- **Changes requested** has no GitLab equivalent. This field is always
  reported as `false`.
- **Reviewer count** only counts users who have approved, not all assigned
  reviewers.

These gaps are tracked internally and may be refined in future releases.

## Troubleshooting

### Diffs not appearing on GHE

Add `API_BASE_URL` to your GHE external auth config and restart Coder.
Diffs should appear within a couple of minutes.

### Users not seeing diffs

The chat owner must have linked their account through the relevant external
auth provider.

<a id="checking-logs"></a>

### Check logs

Look for gitsync warnings such as `no provider for origin` or
`resolve token` errors.

---

# Conversation data retention

Source: https://coder.com/docs/ai-coder/agents/platform-controls/chat-retention

Coder Agents automatically cleans up old conversation data to manage database
growth. Archived conversations and their associated files are periodically
purged based on a configurable retention period.

Conversations become eligible for purging only after they are archived. Old
conversations can be archived manually, or automatically. See
[Auto-Archive](./chat-auto-archive.md) for how the two controls interact.

Debug run and step cleanup is controlled separately. See
[Chat Debug Data Retention](./chat-debug-retention.md).

## How it works

A background process runs approximately every 10&nbsp;minutes to remove expired conversation data.
Only archived conversations are eligible for deletion.
Active (non-archived) conversations are never purged.

When an archived conversation exceeds the retention period, Coder deletes it along with its messages, diff statuses, and queued messages.
Coder retains an attached file while any conversation references it, regardless of whether the conversation is active or archived.
A file that exceeds the retention period becomes eligible for deletion only after no conversations reference it.
Conversation and file cleanup operations run in batches of 1,000 rows per cycle.

## Configuration

Navigate to **Admin settings** > **AI** > **Coder Agents** > **Lifecycle** to configure the conversation retention period.
The default is 30&nbsp;days.
Use the toggle to disable retention entirely.

Use the admin API to read or update the value:

```txt
GET  /api/v2/chats/config/retention-days
PUT  /api/v2/chats/config/retention-days
```

## What gets deleted

| Data                   | Condition                                                          | Cascade                                                       |
|------------------------|--------------------------------------------------------------------|---------------------------------------------------------------|
| Archived conversations | Archived longer than retention period                              | Messages, diff statuses, queued messages deleted via CASCADE. |
| Conversation files     | Older than retention period and not referenced by any conversation | None                                                          |

## Unarchive safety

Archiving a conversation does not make its attached files eligible for deletion.
If you unarchive a conversation before Coder purges it, its attachments remain available, even when the files exceed the retention period.

---

# Chat debug data retention

Source: https://coder.com/docs/ai-coder/agents/platform-controls/chat-debug-retention

Coder Agents automatically cleans up old chat debug data to manage database
growth. Debug data includes persisted debug runs and their associated debug
steps.

This setting is independent from [conversation data retention](./chat-retention.md),
which only purges archived conversations and orphaned files.

## How it works

A background process removes debug runs older than the configured retention
period. When a debug run is deleted, its debug steps are deleted via cascade.

The retention clock uses the debug run's `updated_at` value, which reflects the
last write to the debug run. It does not use the chat archive time. If a debug
run remains in progress for an unusually long period, such as after broken
finalization, it can still be purged once its `updated_at` value is older than
the cutoff.

## Configuration

Navigate to **Admin settings** > **AI** > **Coder Agents** > **Lifecycle** to configure chat debug data retention.
The default is 30&nbsp;days.
Set the value to `0` to disable debug data retention entirely.
The maximum value is `3650` days.

Use the admin API to read or update the value:

```txt
GET  /api/v2/chats/config/debug-retention-days
PUT  /api/v2/chats/config/debug-retention-days
```

## Interaction with conversation retention

Conversation retention and debug data retention are orthogonal controls:

| Control                | What it deletes                                             | Default      |
|------------------------|-------------------------------------------------------------|--------------|
| Conversation retention | Archived conversations and orphaned files                   | 30&nbsp;days |
| Debug data retention   | Debug runs and debug steps, based on debug run `updated_at` | 30&nbsp;days |

Deleting a chat still deletes its debug data immediately via cascade, regardless
of the debug retention window. Unarchiving a chat does not restore debug data
that was already purged.

---

# Conversation auto-archive

Source: https://coder.com/docs/ai-coder/agents/platform-controls/chat-auto-archive

Coder Agents automatically archives long-inactive conversations so they
drop out of active chat lists without any user intervention. Archived
conversations are still visible (and can be unarchived) until they age
out of the separate retention window, at which point they are purged.

## How it works

The Coder Agents chat worker scans the chat database once an hour for root conversations where the most recent non-deleted message predates the configured auto-archive window, and flips them from "active" to "archived".
Eligibility is evaluated at UTC day boundaries: all conversations with last activity falling on the same UTC date are archived together on the first tick after midnight UTC following the expiration of their archive window.
Cascaded child chats are archived alongside their parent so the conversation stays coherent.

Activity is defined as the most recent non-deleted message in the conversation family, counting messages from every role.
Root chats that have ongoing work are never selected for auto-archiving.
Children inherit their root's archival decision.

Pinned root conversations (those with a non-zero pin order) are never
selected for auto-archiving. Children are archived alongside their
root regardless of individual pin status. Admins and users who want
to retain a conversation long after its last message should pin the
root.

## Notifications

When your chats are auto-archived, you receive a digest notification
listing the titles of the archived conversations and the
auto-archive window currently configured. Because eligibility uses
UTC day boundaries, in steady state this notification fires at most
once per day (on the first tick after midnight UTC that finds newly
eligible chats). A large backlog (initial enablement or bulk
inactivity) may span multiple ticks, producing multiple notifications
until the backlog drains.

Each digest lists at most 25 conversation titles.
When a tick archives more than that, the notification names the first 25 and reports the remainder as a count.

If you find the digest noisy, you can disable the "Chats
Auto-Archived" notification entirely from your notification preferences.

## Interaction with retention

Auto-archive and deletion are two independent controls:

| Control             | What it does                                                              | Default                |
|---------------------|---------------------------------------------------------------------------|------------------------|
| Auto-archive window | Moves inactive chats to the archived state                                | 0&nbsp;days (disabled) |
| Retention window    | Deletes chats that have been archived long enough and orphaned chat files | 30&nbsp;days           |

A conversation needs to be inactive for `auto_archive_days`, then
archived for `retention_days`, before it is deleted. The two windows
stack additively. With auto-archive disabled by default, inactive
chats are never auto-archived; once an admin opts in by setting a
non-zero `auto_archive_days`, a conversation lives for at least
`auto_archive_days + retention_days` from its last message before it
is permanently removed.

Auto-archive (like manual archive) resets the per-chat retention
clock, so the full `retention_days` runs from the tick that archived
the chat, not from its last message.

Setting either value to `0` disables that step. Setting
`auto_archive_days` to `0` means inactive chats are never
auto-archived (users still archive manually). Setting
`retention_days` to `0` means archived chats are kept indefinitely.

## Configuration

The auto-archive window is stored as the
`agents_chat_auto_archive_days` key in the `site_configs` table.
The default is `0` (disabled); set to a positive number of days to
enable auto-archiving.

Admins can set the window in the dashboard under **AI Settings** > **Coder Agents** > **Lifecycle**.

Use the admin API to read or update the value:

    GET  /api/v2/chats/config/auto-archive-days
    PUT  /api/v2/chats/config/auto-archive-days

## Rollout advice

Auto-archive is disabled by default, so upgrading to a release that includes this feature will not archive any existing chats until an admin opts in.
The first tick after enabling auto-archive on a deployment with a long history will process up to 1,000 root chats (and their children).
If your deployment has a large backlog, the initial rollout will span many ticks.
This is intentional and keeps each tick bounded so auto-archive doesn't crowd out the chat worker's other background work.
To disable, set `auto_archive_days` back to `0`.

## Audit trail

Each auto-archived root chat produces an audit log entry with the
background subsystem tag `chat_auto_archive`. Cascaded children are
not audited individually.

---

# Advisor

Source: https://coder.com/docs/ai-coder/agents/platform-controls/advisor

> [!NOTE]
> This feature is experimental. Pin a release before broad rollout and review
> the release notes before upgrading.

## Enable the experiment

```sh
coder server --experiments=chat-advisor
```

Or set the environment variable:

```sh
CODER_EXPERIMENTS=chat-advisor
```

## What it does

Lets a root agent pause its current turn and request strategic guidance from
a separate, single-step model call. The advisor sees recent conversation
context, runs without any tools, and returns concise advice for the root
agent rather than the end user. While active, it is the only tool the root
agent can call for that turn.

Useful for planning ambiguity, architectural tradeoffs, debugging strategy
after repeated failures, or risk reduction before a destructive operation.

## Configuration

Once the experiment is enabled, configure the advisor's runtime limits
under **Admin settings** > **AI** > **Coder Agents** > **Deployment settings**.
Use the **Advisor** card. These limits apply deployment-wide.

| Field             | Default              | Notes                                                                                                                   |
|-------------------|----------------------|-------------------------------------------------------------------------------------------------------------------------|
| Max uses per turn | `0` (unlimited)      | Caps how many times the root agent can call the advisor in a single chat turn. Must be a non-negative integer.          |
| Max output tokens | `0` (server default) | Caps the advisor model's response length. `0` uses the server default of 16,384 tokens. Must be a non-negative integer. |

The advisor model and its reasoning effort are organization-scoped [model overrides](../models.md#model-overrides).
Configure them in the **Organization settings** section of **Admin settings** > **AI** > **Coder Agents** for the selected organization.
When no override is set, the advisor reuses the root agent's model.

The advisor is not available in plan mode or to subagents.
Failed advisor invocations refund the per-turn budget.

The same configuration is available through the API: runtime limits at
`GET`/`PUT` `/api/experimental/chats/config/advisor`, and the advisor
model override at
`PUT /api/v2/organizations/{organization}/chats/model-overrides/advisor`.

---

# Virtual desktop

Source: https://coder.com/docs/ai-coder/agents/platform-controls/virtual-desktop

> [!NOTE]
> This feature is experimental. Pin a release before broad rollout and review
> the release notes before upgrading.

## Enable the experiment

```sh
coder server --experiments=chat-virtual-desktop
```

Or set the environment variable:

```sh
CODER_EXPERIMENTS=chat-virtual-desktop
```

## What it does

Lets agents drive a graphical desktop inside the workspace through
`spawn_agent` with `type=computer_use` (screenshots, mouse, keyboard).

## Configuration

Once the experiment is enabled, configure the computer-use provider under
**Admin settings** > **AI** > **Coder Agents** > **Deployment settings**.
Use the **Virtual desktop** card.

Choose a **Computer use provider** (Anthropic or OpenAI). Virtual desktop also requires:

- The [portabledesktop](https://registry.coder.com/modules/coder/portabledesktop)
  module installed in the workspace template.
- An API key for the selected provider configured under the **Providers**
  sidebar item.

The Anthropic and OpenAI computer-use models are fixed by Coder per provider
and are not selectable from this UI. Anthropic is the default when no
provider is set.

The same configuration is available at:

- `GET /api/v2/chats/config/computer-use-provider`
- `PUT /api/v2/chats/config/computer-use-provider`

---

# Chat debug logging

Source: https://coder.com/docs/ai-coder/agents/platform-controls/chat-debug-logging

Records a detailed trace of each chat turn for troubleshooting: the
normalized request sent to the LLM provider, the full response, token usage,
retry attempts, and errors.

Off by default. Three layers control whether it runs for a given chat:

1. **Deployment override.** Setting `CODER_CHAT_DEBUG_LOGGING_ENABLED=true`
   (or `--chat-debug-logging-enabled` at server start) forces debug logging
   on for every chat. The runtime admin and user toggles become read-only.
1. **Runtime admin gate.** With the deployment override unset, the
   *Let users record chat debug logs* toggle decides whether users can opt
   in. Configure it under **Admin settings** > **AI** > **Coder Agents** > **Lifecycle**, or at
   `GET/PUT /api/v2/chats/config/debug-logging`.
1. **Per-user toggle.** Users with the admin gate enabled can turn debug
   logging on for their own chats from **Agents** > **Settings** > **General**
   under *Record debug logs for my chats*. The endpoint
   `PUT /api/v2/chats/config/user-debug-logging` returns
   `409 Conflict` if the deployment override is active and `403 Forbidden`
   if the admin has not enabled user opt-in.

> [!IMPORTANT]
> Debug logs may contain sensitive content from prompts, responses, tool
> calls, and errors. Treat them with the same care as conversation history.
> Only the chat owner (or a user with read access to the chat) can fetch a
> chat's debug runs through the API. Administrators do not get blanket
> access to all users' debug data.

When debug logging is active for a chat, a **Debug** tab appears in the
right panel of the Agents page (alongside Git, Terminal, and Desktop) for
that chat's owner. The tab lists recent debug runs and lets you expand a run
into its per-step request, response, token usage, retry attempts, errors,
and policy metadata.

## Export debug logs

You can export the same captured debug data from the UI:

1. Navigate to **Agents**.
1. Open a chat with debug logging enabled.
1. Open the **Debug** tab in the right panel.
1. Select **Export debug logs** to download the chat's recent debug runs as JSON, or expand a run and select **Export this run** to download one run.

The chat-level export includes the full run detail for the runs returned by
the debug run list endpoint. The current list endpoint returns up to 100 of
the newest runs.

### API access

The same data is available through the API:

- `GET /api/v2/chats/{chat}/debug/runs` lists the most recent runs
  for a chat (up to 100, newest first).
- `GET /api/v2/chats/{chat}/debug/runs/{debugRun}` returns a single
  run with all of its steps, including normalized request and response bodies.

Fetch a single run and save it as JSON:

```sh
export CODER_URL="https://coder.example.com"
export CODER_SESSION_TOKEN="$(coder login token)"
export CHAT_ID="00000000-0000-0000-0000-000000000000"
export RUN_ID="11111111-1111-1111-1111-111111111111"

curl -fsS \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  "$CODER_URL/api/v2/chats/$CHAT_ID/debug/runs/$RUN_ID" \
  | jq . > "coder-agents-debug-run-$RUN_ID.json"
```

Fetch every run returned by the list endpoint and save a chat-level export.
Using the same `CODER_URL`, `CODER_SESSION_TOKEN`, and `CHAT_ID` variables
from above:

```sh
RUN_IDS=$(curl -fsS \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  "$CODER_URL/api/v2/chats/$CHAT_ID/debug/runs" \
  | jq -r '.[].id') || {
  echo "Failed to list debug runs" >&2
  exit 1
}

RUN_EXPORTS=$(mktemp)
trap 'rm -f "$RUN_EXPORTS"' EXIT

for RUN_ID in $RUN_IDS; do
  curl -fsS \
    -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
    "$CODER_URL/api/v2/chats/$CHAT_ID/debug/runs/$RUN_ID" \
    >> "$RUN_EXPORTS" || {
      echo "Failed to fetch debug run $RUN_ID" >&2
      exit 1
    }
  echo >> "$RUN_EXPORTS"
done

jq -s \
  --arg chat_id "$CHAT_ID" \
  --arg exported_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  '{
    version: 1,
    scope: "chat",
    exported_at: $exported_at,
    chat_id: $chat_id,
    run_count: length,
    limited_to_most_recent: 100,
    runs: .
  }' "$RUN_EXPORTS" > "coder-agents-debug-chat-$CHAT_ID.json"
```

Debug runs are stored alongside the chat and are removed when the parent
conversation is deleted (manually, by retention, or by chat purge). See
[Data Retention](./chat-retention.md) for the conversation retention
controls.

---

# Extending Agents

Source: https://coder.com/docs/ai-coder/agents/extending-agents

Workspace templates can extend the agent with custom skills and MCP tools.
These mechanisms let platform teams provide repository-specific instructions,
domain expertise, and external tool integrations without modifying the agent
itself.

## How the workspace shares context with chats

The workspace agent owns discovery.
It scans a fixed set of locations for instruction files, skills, and MCP configuration, then pushes the result to Coder as a single context snapshot.
Chats never scan the workspace themselves; they read the snapshot the agent pushed.

A workspace-attached chat pins one snapshot.
The pinned copy is what the agent's system prompt and tool list are built from, so a chat keeps working with a consistent view of your skills and MCP tools even while you edit files in the workspace.

The lifecycle of an edit looks like this:

1. You add a skill, edit `.mcp.json`, or change an instruction file in the workspace.
1. A file watcher notices the change, and the agent re-scans after a short period and then pushes a new snapshot.
1. Chats that have not pinned a snapshot yet pin the new one immediately.
1. Chats that already pinned an older snapshot are marked out of date instead of being switched over.
1. Selecting **Refresh context** in the chat re-pins that chat to the latest snapshot.

This is why an in-flight chat can keep using an older snapshot: a push never rewrites a chat's pinned context.
The pin only moves when the chat is first hydrated or when you refresh it.

The agent publishes nothing until the workspace is ready.
Until startup scripts finish, the agent holds an empty snapshot, so a chat opened during workspace startup can show no skills and no MCP tools until the first real push lands.

### Where the agent looks

Each scan location is a scan root.
The agent scans the following:

- The workspace working directory
- `~/.coder` and `~/.coder/skills`
- `~/.claude/plugins/cache`
- Any additional source you declare through the agent's context sources API

Declared sources contribute instruction files and skills only.
A `.mcp.json` file inside a declared source appears in the context inventory, but the agent does not connect to the servers it lists; MCP servers load only from the workspace working directory.

Discovery is shallow.
Instruction files (`AGENTS.md`, `CLAUDE.md`, `.cursorrules`) and `.mcp.json` are read only at the top level of a scan root, and skills are read only from the fixed container directories described below.
The agent never walks further down the tree and never climbs to a parent directory.
To pick up context in another directory, declare that directory as its own source.

### Snapshot limits

A snapshot is capped so a large workspace cannot flood a chat's prompt:

| Limit                                        | Behavior when exceeded                                                                                   |
|----------------------------------------------|----------------------------------------------------------------------------------------------------------|
| 64&nbsp;KiB per file resource                | The resource is reported with an oversize status and no content, so the chat lists it but cannot read it |
| 2&nbsp;MiB of file content across a snapshot | Resources past the cap are reported as excluded with no content                                          |
| 500 resources per snapshot                   | Resources past the cap are reported as excluded with no content                                          |

The byte caps measure file contents, such as instruction files and skill files.
MCP server entries count toward the 500-resource cap, but their tool definitions are not measured by the byte caps.

Excluded and oversize resources still appear in the chat's context list with their status and error, so a dropped skill or instruction file is visible rather than silently missing.

## Skills

Skills are structured, reusable instruction sets that the agent loads on
demand. They live in the workspace filesystem and are discovered
automatically when a chat attaches to a workspace.

### How skills work

A skill is a directory containing a required `SKILL.md` file and any supporting files the skill needs.
The agent looks for skill directories in the immediate children of these containers, relative to each scan root:

- `skills/`
- `.agents/skills/`
- `.claude/skills/`
- `.codex/skills/`

Because `~/.coder/skills` is itself a scan root, skills placed directly under it are discovered too.

Each discovered skill contributes its name and description to the `<available-skills>` block in the agent's system prompt.
The full instructions are loaded only when the agent calls a tool, and they are served from the chat's pinned snapshot rather than read live from the workspace.
A skill added after a chat pinned its snapshot appears in that chat after you refresh its context.

Two tools are registered when skills are present:

| Tool              | Parameters                       | Description                                                                                                |
|-------------------|----------------------------------|------------------------------------------------------------------------------------------------------------|
| `read_skill`      | `name` (string)                  | Returns the SKILL.md body, the absolute skill directory (workspace skills), and a list of supporting files |
| `read_skill_file` | `name` (string), `path` (string) | Returns the content of a supporting file                                                                   |

For workspace skills, `read_skill` also returns `dir`, the absolute path to
the skill directory in the workspace. The agent's `read_file` and `execute`
tools operate on that same workspace filesystem, so you can join `dir` with a
supporting file's relative path to read or run that file directly, for example
to execute a bundled `scripts/` helper. `read_skill_file` remains available as
a path-safe convenience for reading supporting files.

Supporting files are read over the workspace connection, so `read_skill_file` and the supporting-file list need a reachable workspace.
The skill body comes from the pin and keeps working when the workspace is unreachable.

### Directory structure

```txt
.agents/skills/
├── deep-review/
│   ├── SKILL.md
│   └── roles/
│       ├── security-reviewer.md
│       └── concurrency-reviewer.md
├── pull-requests/
│   └── SKILL.md
└── refine-plan/
    └── SKILL.md
```

### SKILL.md format

Each `SKILL.md` starts with YAML frontmatter containing a `name` and an
optional `description`, followed by the full instructions in markdown:

```md
---
name: deep-review
description: "Multi-reviewer code review with domain-specific reviewers"
---

# Deep Review

Instructions for the skill go here...
```

### Naming and size constraints

- Names must be kebab-case (`^[a-z0-9]+(-[a-z0-9]+)*$`) and match the
  directory name exactly.
- `SKILL.md` has a maximum size of 64&nbsp;KB.
  A larger file is reported with an oversize status and contributes no content to the chat.
- Supporting files have a maximum size of 512&nbsp;KB.
  Files exceeding the limit are silently truncated.

A skill with its frontmatter missing, unparsable, not kebab-case, or not matching its directory name is reported as invalid and contributes no instructions.

### Path safety

`read_skill_file` rejects absolute paths, paths containing `..`, and
references to hidden files. All paths are resolved relative to the skill
directory.

## Personal skills

Personal skills are user-owned skills that are available to all of your
chats. They are not tied to a specific workspace. Manage them from the
**Agents** page, under **Settings** > **Personal Skills**.

Personal skills use the same `SKILL.md` format as workspace skills: YAML
frontmatter with a kebab-case `name`, an optional `description`, and a
markdown body. This keeps content portable between personal skills and
workspace skills.

```md
---
name: personal-reviewer
description: "Personal review guidance"
---

# Personal Reviewer

Instructions for the skill go here...
```

Each personal skill is stored as a single `SKILL.md` file containing
frontmatter and body content. Supporting files are not supported. Each
`SKILL.md` file can be up to 64&nbsp;KB, and each user can create up to 100 personal skills.

Personal skills are stored in Coder, not in the workspace, so they are not part of a workspace context snapshot and do not depend on a pin or a refresh.

If you need richer skills with supporting files or multiple files, use
workspace skills instead. Store them in the repo under
`.agents/skills/<name>/`, or load them from a workspace.

## Workspace MCP tools

Workspace templates can expose custom
[MCP](https://modelcontextprotocol.io/introduction) tools by placing a
`.mcp.json` file in the workspace working directory.
The agent connects to these servers, reports their tools in the context snapshot it pushes, and chats register those tools alongside their built-in tools.
To declare an MCP server inline on one chat through the API instead, refer to [Inline MCP servers](./platform-controls/mcp-servers.md#inline-mcp-servers-experimental).

### Configuration

Define MCP servers in `.mcp.json` at the workspace root. Each entry under
`mcpServers` describes a server. The transport type is inferred from
whether `command` or `url` is present, or you can set it explicitly with
`type`:

```json
{
  "mcpServers": {
    "github": {
      "command": "github-mcp-server",
      "args": ["--token", "..."]
    },
    "my-api": {
      "type": "http",
      "url": "http://localhost:8080/mcp",
      "headers": { "Authorization": "Bearer ..." }
    }
  }
}
```

**Stdio transport**: set `command`, and optionally `args` and `env`. The
agent spawns the process in the workspace.

**HTTP transport**: set `url`, and optionally `headers`. The agent connects
to the HTTP endpoint from the workspace.

### How discovery works

The agent connects to the servers declared in `.mcp.json` once startup scripts finish.
Servers that fail to connect are skipped, and the rest still contribute their tools.

A single set of connections is shared by tool discovery and tool execution, so each declared server is launched once.
When the connected tool list changes, the agent re-scans and pushes a new snapshot.

Editing `.mcp.json` does not require a workspace restart.
The agent notices edits to the file and reloads its servers automatically.
The reload changes the pushed snapshot, but an MCP-only change does not mark existing chats out of date, and the dashboard offers **Refresh context** only on chats that are marked out of date.
New chats and chats that have not pinned a snapshot yet receive the new tool set immediately.
An existing chat keeps its current tool set until another context change, such as editing an instruction file or a skill, marks it out of date; refreshing then re-pins the whole snapshot, including the new MCP tools.

The snapshot carries tool definitions only, not a way to run them.
Every workspace MCP tool call is proxied back through the workspace agent, so a chat can list workspace MCP tools while the workspace is unreachable, but calling one requires a running workspace with the server connected.

### Tool naming

Tool names are prefixed with the server name as `serverName__toolName` to
avoid collisions between servers and with built-in tools.

### Timeouts

- **Server connect**: 30&nbsp;seconds per server.
- **Tool calls**: 60&nbsp;seconds per invocation.

---

# Models

Source: https://coder.com/docs/ai-coder/agents/models

Administrators configure LLM providers from **Admin settings** > **AI** and Coder Agents models from **Admin settings** > **AI** > **Models**.
Providers and centrally managed credentials are deployment-wide settings managed by platform teams.
Each model belongs to an organization. Each organization has its own model list.
Developers select from the set of models that an administrator has enabled in their organization.
Refer to [Organization scope](./platform-controls/organizations.md) for the split between deployment-wide and organization-scoped settings.

Optionally, administrators can enable AI Gateway Bring Your Own Key (BYOK)
so developers can supply personal API keys for providers. See
[User API keys](#user-api-keys-byok) below.

## Providers

Each LLM provider has a type, credentials, and an endpoint/base URL for the
upstream provider or proxy.

Coder supports the following provider types:

| Provider          | Description                              |
|-------------------|------------------------------------------|
| Anthropic         | Claude models via Anthropic API          |
| OpenAI            | GPT and o-series models via OpenAI API   |
| Google            | Gemini models via Google AI API          |
| Azure OpenAI      | OpenAI models hosted on Azure            |
| AWS Bedrock       | Models via AWS Bedrock                   |
| OpenAI Compatible | Any endpoint implementing the OpenAI API |
| OpenRouter        | Multi-model routing via OpenRouter       |
| Vercel AI Gateway | Models via Vercel AI SDK                 |

The **OpenAI Compatible** type is a catch-all for any service that exposes an
OpenAI-compatible chat completions endpoint. Use it to connect to self-hosted
models, internal gateways, or third-party proxies like LiteLLM.

Coder Agents route model requests through AI Gateway automatically by using
the provider configuration stored in Coder's database.

Some provider types work as AI Gateway proxy targets but cannot back Coder
Agents. GitHub Copilot, for example, authenticates with a per-request token
that only an official Copilot client can mint, so the server-side Agents
harness cannot use it. Configuring such a provider does not unlock Agents;
add one of the supported provider types above instead.

### Add a provider

LLM providers are managed from the deployment AI settings, not from the Agents settings page.
A provider is deployment-wide, whilst the models that reference it are organization-scoped.

1. Navigate to **Admin settings** > **AI**.
1. Select **Providers**.
1. Select **Add provider**.
1. Select the provider type.
1. Enter a unique lowercase provider name, the credentials, and the upstream
   provider or proxy
   [endpoint/base URL](#endpointbase-url-for-openai-compatible-providers).
1. Select **Save**.

After saving a provider, add an Agents model for it from **Admin settings** > **AI** > **Models**.
Select the organization that should own the new model before you add it.
For provider-specific setup, including AWS Bedrock, refer to [AI Gateway provider configuration](../ai-gateway/providers.md#provider-types).

## Endpoint/base URL for OpenAI-compatible providers

Provider configuration stores an absolute HTTP(S) endpoint/base URL. Syntax
validation confirms that the value is a URL, but it does not prove the upstream
implements the APIs Coder sends.

For the default Agents path through AI Gateway, set the endpoint/base URL to
the upstream provider or proxy endpoint. Do not set it to Coder's public AI
Gateway route, such as `https://<coder-host>/api/v2/ai-gateway/openai/v1`.

OpenAI-shaped provider types require the upstream OpenAI-compatible prefix in
the endpoint/base URL because Coder appends request suffixes such as
`/chat/completions`, `/responses`, and `/models`. This applies to **OpenAI**,
**Azure OpenAI**, **Google**, **OpenAI Compatible**, **OpenRouter**, and
**Vercel AI Gateway** provider types.

Examples:

| Provider type                       | Example endpoint/base URL                                  |
|-------------------------------------|------------------------------------------------------------|
| OpenAI                              | `https://api.openai.com/v1/`                               |
| Azure OpenAI                        | `https://<resource-name>.openai.azure.com/openai/v1`       |
| Google Gemini OpenAI-compatible API | `https://generativelanguage.googleapis.com/v1beta/openai/` |
| OpenRouter                          | `https://openrouter.ai/api/v1`                             |
| Vercel AI Gateway                   | `https://ai-gateway.vercel.sh/v1`                          |
| Generic OpenAI-compatible proxy     | `https://provider.example.com/v1`                          |

Confirm the exact endpoint/base URL in your provider or proxy documentation.

## Provider credentials and security

Provider API keys entered in the dashboard are stored encrypted in the Coder
database. They are never exposed to workspaces, developers, or the browser
after initial entry. The dashboard shows only whether a key is set, not the
key itself.

Because the agent loop runs in the control plane, workspaces never need direct
access to LLM providers. See
[Architecture](./architecture.md#no-api-keys-in-workspaces) for details
on this security model.

## Credential selection

Coder Agents use the AI providers configured by administrators.
Provider API keys entered by administrators are centralized credentials for the deployment.

BYOK for Coder Agents is controlled by the
[global AI Gateway BYOK setting](../ai-gateway/auth.md#bring-your-own-key-byok),
not by per-provider key policy flags. When BYOK is enabled, users can save a
personal API key for any enabled AI provider. When BYOK is disabled, saved user
keys are ignored and users cannot add or update personal keys.

For AWS Bedrock providers, the personal key is an AWS Bedrock API key. AI
Gateway forwards it as a bearer token, which authenticates that user's requests
instead of the deployment-managed AWS credentials (SigV4). This applies to
every model family Bedrock serves, including Anthropic and OpenAI models.

For each provider request, Coder selects credentials in this order:

1. If BYOK is enabled and the user has saved a personal key for the selected
   provider, Coder uses the user's key.
1. Otherwise, Coder uses centralized provider credentials when they are
   configured.
1. If neither a usable user key nor centralized credentials are available, the
   provider is unavailable for that user.

## Models

Each model belongs to a provider and has its own configuration for context limits,
generation parameters, and provider-specific options.

### Select an organization

Model settings use the stable path `/ai/settings/models` and the `org` query parameter to select an organization.
For example, `/ai/settings/models?org=engineering` opens the models that you can read in the `engineering` organization.

If the requested organization isn't accessible, Coder selects your accessible default organization or your first accessible organization.
Coder shows the organization picker when you can access more than 1 organization.

Members with model read access can open the model list and model details.
Coder shows model fields as read-only unless the member also has update permission.
Create, update, delete, and share permissions control their corresponding actions independently.

### Manage model permissions

Members with model share permission can let members and groups in the selected organization use the model.

Model access lists control which models a member can use in Coder Agents.
Chat permissions come from the **Coder Agents User** role, which every member except service accounts holds by default; see [Control who can use Coder Agents](./getting-started.md#control-who-can-use-coder-agents).
A member without read access to at least one model in the organization can't use the feature.
New models grant read access to the whole organization by default.

1. Navigate to **Admin settings** > **AI** > **Models**.
2. Select the organization that owns the model.
3. Select the model.
4. Open **Model actions** and select **Manage permissions**.
5. Add or remove organization members and groups.
6. Select **Save permissions**.

Coder applies the member and group changes when you save.
Removing all entries clears the model's access list, so members without another access grant cannot use the model on their next request.

### Model visibility and runtime availability

Management visibility and runtime availability are separate.
A member can see a model in settings through its access list even when the model isn't available for chat.

The Agents model selector includes the model only when its exact provider configuration has usable credentials for that member.
Coder evaluates providers by provider UUID, so 2 providers of the same type can have different availability.
An unavailable provider can remain visible while its models are omitted from the selector.

Model APIs identify each configured model with a UUID.
The provider's model identifier, such as `gpt-5.3-codex`, doesn't replace this model UUID.

### Migrate model API clients

Model collection APIs require an organization name or ID in the path.
Update clients that use the removed default-organization routes as follows:

| Removed route                                | Replacement                                              | Response change                                                                                                             |
|----------------------------------------------|----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
| `GET /api/experimental/chats/models`         | `GET /api/v2/organizations/{organization}/chats/models`  | The response remains an `OrganizationChatModelsResponse`.                                                                   |
| `GET /api/experimental/chats/model-configs`  | `GET /api/v2/organizations/{organization}/chats/models`  | The response changes from a `ChatModel` array to an `OrganizationChatModelsResponse`. Read configured models from `models`. |
| `POST /api/experimental/chats/model-configs` | `POST /api/v2/organizations/{organization}/chats/models` | The request and `ChatModel` response shapes remain the same.                                                                |

Replace `{organization}` with the organization name or ID that owns the models.
The collection response also includes provider descriptors and unsupported provider details.

### Add a model

1. Navigate to **Admin settings** > **AI** > **Models**.
1. Select **Add model** and select the provider for the new model.
1. Enter the **Model Identifier**, the exact model string your provider
   expects (e.g., `claude-opus-4-6`, `gpt-5.3-codex`).
1. Set a **Display Name** so developers see a human-readable label in the model
   selector.
1. Set the **Context Limit**, the maximum number of tokens in the model's
   context window (e.g., `200000` for Claude Sonnet).
1. Configure any provider-specific options (see below).
1. Select **Save**.

<img src="../../images/guides/ai-agents/models-list.png" alt="Screenshot of the models list in the Agents settings">

<small>The models list shows all configured models grouped by provider.</small>

<img src="../../images/guides/ai-agents/models-add-model.png" alt="Screenshot of the add model form">

<small>Adding a model requires a model identifier, display name, and context
limit. Provider-specific options appear dynamically based on the selected
provider.</small>

### Set a default model

Each organization has one default model.
The first model that you add to an organization becomes that organization's default model.
The models list marks the current default with a **Default** badge.
The default model is pre-selected when developers start a new chat in the organization.

To change the default model from the Models page:

1. Navigate to **Admin settings** > **AI** > **Models**.
1. Select the organization that owns the model.
1. Open the model, or select **Add model** to create a new one.
1. Select **Set as Coder Agents default model**.
1. Select **Save**.

To change it from the Coder Agents page, navigate to **Admin settings** > **AI** > **Coder Agents**, pick a model in the **Default model** row of **Organization settings**, and select **Save**.
If the current default is disabled or its provider is unavailable, the row shows a warning and still lets you pick another model.

### Models with a missing or disabled provider

The Models list reflects whether each model can actually be used:

- When a model's connected provider has been deleted, the **Provider** column
  shows **Unset**.
- When a model's provider is missing or disabled, an **Unavailable** badge
  appears beside the model name. The badge's tooltip explains whether the
  provider was deleted or disabled. Such a model cannot serve chat requests.
- When a model is disabled, a **Disabled** badge appears beside the model name.

To reconnect a model to a working provider, open the model from the list, pick a new provider from the **Provider** dropdown, and select **Save**.
The Save button is enabled as soon as the selected provider differs from the model's current provider, even if no other field is edited.

## Model options

Every model has a set of general options and provider-specific options.
The admin UI generates these fields automatically from the provider's
configuration schema, so the available options always match the provider type.

### General options

These options apply to all providers:

| Option                | Description                                                                                      |
|-----------------------|--------------------------------------------------------------------------------------------------|
| Model Identifier      | The API model string sent to the provider (e.g., `claude-opus-4-6`).                             |
| Display Name          | The label shown to developers in the model selector.                                             |
| Context Limit         | Maximum tokens in the context window. Used to determine when context compaction triggers.        |
| Compression Threshold | Percentage (0-100) of context usage at which the agent compresses older messages into a summary. |
| Max Output Tokens     | Maximum tokens generated per model response.                                                     |
| Temperature           | Controls randomness. Lower values produce more deterministic output.                             |
| Top P                 | Nucleus sampling threshold.                                                                      |
| Top K                 | Limits token selection to the top K candidates.                                                  |
| Presence Penalty      | Penalizes tokens that have already appeared in the conversation.                                 |
| Frequency Penalty     | Penalizes tokens proportional to how often they have appeared.                                   |

### Provider-specific options

Each provider type exposes additional options relevant to its models. These
fields appear dynamically in the admin UI when you select a provider.

#### Anthropic

| Option                 | Description                                                                                                                                                                                                                      |
|------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Thinking Budget Tokens | Maximum tokens allocated for extended thinking.                                                                                                                                                                                  |
| Effort                 | Thinking effort level (`low`, `medium`, `high`, `xhigh`, `max`).                                                                                                                                                                 |
| 1M Context Window      | Sends the `anthropic-beta: context-1m-2025-08-07` header to unlock the 1M token context window on supported Claude models. Pair it with a raised Context Limit, which still controls compaction. Long-context pricing may apply. |

#### OpenAI

| Option                | Description                                                                                                                                                                                                                                                                                                                                          |
|-----------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Reasoning Effort      | How much effort the model spends reasoning (`minimal`, `low`, `medium`, `high`, `xhigh`).                                                                                                                                                                                                                                                            |
| Max Completion Tokens | Cap on completion tokens for reasoning models.                                                                                                                                                                                                                                                                                                       |
| Parallel Tool Calls   | Whether the model can call multiple tools at once.                                                                                                                                                                                                                                                                                                   |
| Reasoning Mode        | Set to `pro` to use OpenAI's Pro reasoning mode. Supported from the GPT-5.6 Sol generation; requests fail on models that do not support it. Pro increases model work, latency, and token usage. It requires the Responses API and a reasoning model, so it is rejected when the **Use Responses API** or **Reasoning Model** override is set to Off. |

#### Google

| Option           | Description                                         |
|------------------|-----------------------------------------------------|
| Thinking Budget  | Maximum tokens for the model's internal reasoning.  |
| Include Thoughts | Whether to include thinking traces in the response. |

#### OpenRouter

| Option            | Description                                       |
|-------------------|---------------------------------------------------|
| Reasoning Enabled | Enable extended reasoning mode.                   |
| Reasoning Effort  | Reasoning effort level (`low`, `medium`, `high`). |

#### Vercel AI Gateway

| Option            | Description                     |
|-------------------|---------------------------------|
| Reasoning Enabled | Enable extended reasoning mode. |
| Reasoning Effort  | Reasoning effort level.         |

> [!NOTE]
> Azure OpenAI uses the same options as OpenAI except Reasoning Mode. AWS
> Bedrock uses the same model configuration options as Anthropic (thinking
> budget, reasoning effort).

## How developers select models

Developers see a model selector dropdown when starting or continuing a chat on the Agents page.
The selector shows only models in the chat's organization that come from providers with valid credentials.
Models are grouped by provider if multiple providers are active.

The model selector uses the following precedence to pre-select a model:

1. **Last used model**, stored in the browser's local storage.
1. **Organization default**, the model marked with the **Default** badge.
1. **First available model**, if no default is set and no history exists.

Developers cannot add their own providers or models. If no models are
configured, the chat interface displays a message directing developers to
contact an administrator.

## Model overrides

Beyond the chat-level model picker, Coder Agents supports two override layers.
Both are stored per organization and resolve from the chat's organization:

- **Admin overrides** (per organization): Pin specific contexts to a particular model.
  Configure them in the **Organization settings** section of **Admin settings** > **AI** > **Coder Agents**.
  Coder shows an organization picker in that section when you can access more than 1 organization.
- **Personal overrides** (per user and organization, opt-in by admin): Let users override the model for their own root chats and delegated subagents.
  Admins enable the deployment-wide toggle in the **Deployment settings** section of the same page.
  Once the toggle is on, each user sees an **Agents** tab in their personal **Agents** > **Settings**.
  Users in more than one organization pick which organization to configure.

The **Coder Agents** page is visible to deployment admins and to organization members with model access.
To change an organization override, you need permission to edit that organization's models.
The **Deployment settings** section is visible only to deployment admins.

> [!IMPORTANT]
> When a deployment upgrades from the older deployment-wide override
> storage, existing admin and personal overrides are deleted rather than
> migrated. Admins and users must re-select their override models in
> settings after the upgrade.

The configurable contexts:

| Context              | Layer        | Applies to                                                                             |
|----------------------|--------------|----------------------------------------------------------------------------------------|
| **General**          | Admin + user | Write-capable subagents (`spawn_agent` with `type=general` or `computer_use`).         |
| **Explore**          | Admin + user | Read-only subagents (`spawn_agent` with `type=explore`).                               |
| **Title generation** | Admin only   | Chat titles, turn status labels, and chat summaries.                                   |
| **Compaction**       | Admin only   | Conversation summarization near the context limit.                                     |
| **Advisor**          | Admin only   | The [advisor](./platform-controls/advisor.md). Requires the `chat-advisor` experiment. |
| **Root**             | User only    | The user's own root chats.                                                             |

Resolution order, evaluated per chat or subagent from the chat's
organization:

1. Explicit `model_config_id` on the `spawn_agent` tool call (general and
   explore subagents only).
1. Personal override (when the admin gate is on and a model is set).
1. Admin override.
1. The chat's selected model (or the organization default for new chats).

If a referenced model is later disabled or deleted, that layer is skipped
and resolution falls through to the next, with two exceptions: an unusable
explicit `spawn_agent` `model_config_id` fails the tool call, and an
unusable title generation override skips titles, status labels, and
summaries instead of falling back. Agents discover selectable models (and
their reasoning effort ranges) with the `list_subagent_models` tool, which
only returns enabled models usable with the chat owner's credentials.
Computer-use subagents always run on the administrator-configured
computer-use model and reject explicit model selection.

> [!NOTE]
> Both override layers may change between releases.
> Admin overrides are available through the API at
> `/api/v2/organizations/{organization}/chats/model-overrides`
> and personal overrides at
> `/api/v2/organizations/{organization}/members/{user}/chats/model-overrides`.

## User API keys (BYOK)

When [AI Gateway BYOK](../ai-gateway/auth.md#bring-your-own-key-byok) is
enabled, developers can supply personal API keys for any enabled AI provider
from the Agents settings page.

<a id="managing-personal-api-keys"></a>

### Manage personal API keys

1. Navigate to the **Agents** page in the Coder dashboard.
1. Open **Settings** and select the **API Keys** tab.
1. Each enabled provider is listed with a status indicator:
   - **Key saved**, your personal key is active and will be used for requests to
     that provider.
   - **Shared key**, no personal key is set and Coder is using
     deployment-managed credentials for that provider.
   - **No key**, no personal key or deployment-managed credential is available.
     Add a personal key before you use models from this provider.
1. Enter your API key and select **Save**.

Personal API keys are encrypted at rest using the same database encryption
used for deployment-managed provider secrets. The dashboard never displays a
saved key, only whether one is set.

<a id="removing-a-personal-key"></a>

### Remove a personal key

Select **Remove** on the provider card in the API Keys settings tab.
Subsequent requests use deployment-managed credentials when they are configured for that provider.
If no deployment-managed credential is available, add a new personal key before you use models from that provider.

<a id="using-an-llm-proxy"></a>

## Use an LLM proxy

Organizations that route LLM traffic through a centralized proxy, such as
LiteLLM or an internal gateway, can point a provider's **Endpoint** or **Base
URL** at that upstream proxy endpoint. Enter the API key your proxy expects.

Use the **OpenAI Compatible** provider type if your proxy serves multiple model
families through a single OpenAI-compatible endpoint. Include the proxy
provider's documented OpenAI-compatible path prefix, such as `/v1`, when
required.

This lets you keep existing proxy-level features like per-user budgets, rate
limiting, and audit logging while using Coder Agents as the developer interface.

---

# Tools

Source: https://coder.com/docs/ai-coder/agents/tools

Coder Agents completes work by calling tools: structured functions the agent
invokes during a chat to gather context and take action, such as listing
templates, reading files, running commands, or creating a workspace.

This page explains how tool calls work and documents the tools the agent uses
to select a template and create a workspace.

## How tool calls work

Each turn of a conversation follows the same loop:

1. You send a message.
2. The model decides whether it needs a tool and calls it with structured
   arguments. For example, `list_templates` with `{"query": "docker"}`.
3. Coder executes the tool in the control plane using your identity and
   permissions, and returns a JSON result to the model.
4. The model uses the result to decide what to do next: call another tool or
   reply to you.

Tool calls and their results are visible in the chat timeline, so you can
always inspect what the agent did and why.

Two properties hold for every built-in tool:

- **Your permissions apply.** Tools run with the chat owner's RBAC identity.
  The agent cannot list templates or create workspaces that you could not
  access yourself.
- **Results carry instructions.** Where a decision matters, the tool result
  includes a `next_step` field containing a fixed instruction for the agent,
  such as asking you to choose between similar templates. This keeps agent
  behavior consistent without relying on long prompt rules.

## Workspace creation tools

A chat can start without a workspace.
When the conversation and available tools are sufficient, the agent answers without provisioning one.
If missing tools, skills, MCP integrations, or context block progress, or the task needs workspace file access or execution, the agent provisions a workspace.
You don't need to request a workspace separately for setup needed to complete your task.
The agent uses three tools to provision a workspace:

| Tool               | Purpose                                                   |
|--------------------|-----------------------------------------------------------|
| `list_templates`   | Rank available templates and recommend one when confident |
| `read_template`    | Read a template's parameters and presets                  |
| `create_workspace` | Create the workspace from a chosen template               |

Administrators can restrict which templates these tools can use with the switches on the [Templates page](../platform-controls/template-optimization.md#restrict-available-templates).

### list_templates

`list_templates` returns a ranked shortlist of the active, non-deprecated
templates in the chat's organization, so the agent can pick a template the
same way a colleague would: prefer what matches the request, what you already
use, and what the rest of the organization uses.

#### Arguments

| Argument | Type    | Description                                                                   |
|----------|---------|-------------------------------------------------------------------------------|
| `query`  | string  | Optional text matched against template names, display names, and descriptions |
| `page`   | integer | Optional page number, starting at 1. Each page holds 10 templates             |

#### How templates are ranked

Templates are ordered by query relevance first (when a query is provided),
then by an affinity score computed from your recent usage and organization
popularity. Name and ID break any remaining ties so the order is stable.

##### Query relevance tiers

When a query is provided, each template receives the highest tier that any
of its fields matches:

| Tier | Match                                               |
|------|-----------------------------------------------------|
| 4    | The name or display name equals the query           |
| 3    | The name or display name starts with the query      |
| 2    | The name or display name contains the query         |
| 1    | The description contains the query                  |
| 0    | No match. The template is excluded from the results |

The description is checked only when neither the name nor the display name
matched. Matching is case-insensitive and ignores spaces, hyphens, and
underscores, so `python gpu` matches `python-gpu`. A higher tier always
outranks a lower tier, regardless of usage.

##### Affinity score

Within a relevance tier, or when no query is given, templates are ordered by
an affinity score:

```txt
affinity = 10 x (active + 0.5 x deleted) x 0.5^(days_since_last_use / 14)
         + ln(1 + active_developers)
```

- `active`: your workspaces on the template used in the last 60&nbsp;days.
- `deleted`: your recently deleted workspaces used in the last 60&nbsp;days, counted at half the weight of active ones.
- `days_since_last_use`: days since you last used the template.
  The personal term halves every 14&nbsp;days and is zero when you have no usage in the last 60&nbsp;days.
- `active_developers`: developers in the organization with an active
  workspace on the template, excluding unclaimed prebuilt workspaces.

Personal usage carries ten times the weight of organization popularity, and
popularity grows logarithmically so heavily used templates do not drown out
your own history. Each template is scored independently from its own
signals; one template's usage never affects another's score. The score is
internal and only determines ordering and the recommendation. The response
carries the raw evidence instead: `active_developers`,
`your_workspace_count`, and `last_used_by_you` appear on each template when
they are non-zero.

#### Recommendation and next_step

Beyond the ranked list, the result tells the agent what to do next:

- `recommended_template_id` is present only when the top template is a clear
  winner: it is the only available template, it matches the query at a
  strictly higher tier than every other match, or its affinity score reaches
  at least the score of two active developers and leads the runner-up by a
  clear margin.
- `next_step` is always present and contains one of four fixed instructions:

| Situation                           | `next_step` instruction for the agent                 |
|-------------------------------------|-------------------------------------------------------|
| A template is recommended           | Use `recommended_template_id` with `create_workspace` |
| Top templates are too close to call | Ask you to choose a template                          |
| The query matched nothing           | Retry without a query or ask you                      |
| No templates are available          | Inform you that no templates are available            |

When the agent is told to ask, it presents the choices instead of guessing.
You can always override the recommendation by naming a template yourself.

#### Example

A user asks for "a workspace to debug a Docker image". The agent extracts a
search term and calls `list_templates` with:

```json
{
  "query": "docker"
}
```

The response lists matching templates best-first. Here `docker` is an exact
name match while `docker-gpu` is only a prefix match, so the top template is
a clear winner and is recommended:

```json
{
  "templates": [
    {
      "id": "0f9ab36e-43f6-4d8a-b3e6-6803d9a06f72",
      "name": "docker",
      "display_name": "Docker",
      "description": "Provision Docker containers as Coder workspaces.",
      "active_developers": 14,
      "your_workspace_count": 2,
      "last_used_by_you": "2026-06-09T10:04:18.123456Z"
    },
    {
      "id": "8d2cf2a1-55b0-4c4e-9a3f-41be8a5cd1f0",
      "name": "docker-gpu",
      "display_name": "Docker GPU",
      "description": "Docker workspaces with NVIDIA GPU access.",
      "active_developers": 3
    }
  ],
  "page": 1,
  "recommended_template_id": "0f9ab36e-43f6-4d8a-b3e6-6803d9a06f72",
  "next_step": "Use recommended_template_id with create_workspace. Call read_template first only if you need parameter or preset details."
}
```

The agent follows `next_step` and calls `create_workspace` with the
recommended template. Had the two templates tied (for example, both plain
substring matches with similar usage), the response would omit
`recommended_template_id` and `next_step` would instruct the agent to ask
you to choose.

`next_page` is present only when more results exist.

### read_template

`read_template` reads one template's details: its configurable parameters
(name, type, default, options, and validation rules) and its presets,
including preset parameter values and whether prebuilt workspaces are
available for faster startup.

The agent calls it only when needed, typically when a template has required
parameters or when a preset should be applied. For templates that work with
defaults, the agent skips straight to `create_workspace`.

### create_workspace

`create_workspace` provisions a workspace from a template and waits for it to
become ready, then attaches it to the chat.

| Argument      | Type   | Description                                                                        |
|---------------|--------|------------------------------------------------------------------------------------|
| `template_id` | string | Required. The template UUID from `list_templates`                                  |
| `name`        | string | Optional workspace name. One is generated if omitted                               |
| `parameters`  | object | Optional template parameter values from `read_template`                            |
| `preset_id`   | string | Optional preset UUID. Applies preset parameters and may claim a prebuilt workspace |

Guardrails:

- The agent creates a workspace when missing tools, skills, MCP integrations, or context block progress, when workspace access is needed, or when you ask.
  It prefers existing tools and context when they're sufficient.
  Creating a workspace doesn't make workspace MCP tools available in Plan Mode.
  Workspace readiness doesn't guarantee that skills, MCP tools, or context have finished loading.
  The agent uses available capabilities rather than recreating the workspace to retry discovery.
  It follows the `next_step` from `list_templates`, asking you to choose when no template is recommended.
- The tool is idempotent: if the chat already has a workspace building or
  running, that workspace is returned instead of creating a duplicate.
- Templates that do not allow Coder Agents are rejected.

---

# Chat Sharing

Source: https://coder.com/docs/ai-coder/agents/chat-sharing

Chat sharing lets you give other users or groups read-only access to a Coder Agents conversation.

## Share a chat

1. Open the chat you want to share on the **Agents** page. Only top-level chats can be shared; sub-agent chats inherit sharing from their parent.
1. Select the share icon in the chat top bar.
1. Select the **Search for user or group** field.
1. Search for and select a user or group.
1. Select **Add member** to grant **Read** access.
1. If you shared with a group, copy the chat URL from your browser and send it to the group members.

Coder does not create a separate share link. Users you share with directly receive a **Chat Shared** notification with a link to open the chat. Members who gain access only through a group are not notified.

## Shared chat access

Viewers can open the chat from a direct link, view messages, stream live updates, and download chat attachments. Chats shared by other users can appear in the sidebar under **Shared with you** when they are in the chat list. Pinned shared chats appear under **Pinned**. Viewers reach sub-agent chats by following sub-agent links inside the parent chat or by opening a direct URL.

Viewers have read-only access: they cannot send or edit messages, regenerate the chat title, archive the chat, or change its sharing settings.

## Disable chat sharing

Administrators can disable chat sharing for a deployment with `--disable-chat-sharing`, `CODER_DISABLE_CHAT_SHARING`, or `disableChatSharing`. When disabled, only chat owners can access their chats.

---

# Conversation search syntax

Source: https://coder.com/docs/ai-coder/agents/chat-search-syntax

The chat list endpoint accepts a `q` query parameter for filtering
conversations. All filters use `key:value` syntax. Bare search terms
are rejected; use `title:` for title filtering or `search:` for
full-text search.

## Filters

| Key          | Values                                                           | Description                                                                                                           |
|--------------|------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `title`      | substring                                                        | Case-insensitive substring match. Quote multi-word values.                                                            |
| `archived`   | `true`, `false`                                                  | Filter by archived state. Default: `false`.                                                                           |
| `has_unread` | `true`, `false`                                                  | Conversations with unread assistant messages.                                                                         |
| `status`     | `waiting`, `running`, `error`, `requires_action`, `interrupting` | Conversation state. Comma-separated or repeated values match any of them.                                             |
| `pr_status`  | `draft`, `open`, `merged`, `closed`, `none`                      | Linked pull request state. Comma-separated for OR. `none` matches conversations with no linked pull request.          |
| `diff_url`   | URL                                                              | Match by associated diff URL. Quote values containing colons.                                                         |
| `pr`         | positive integer                                                 | Exact PR number match.                                                                                                |
| `repo`       | substring                                                        | Case-insensitive substring match against git remote origin or URL. Quote values containing colons.                    |
| `pr_title`   | substring                                                        | Case-insensitive PR title substring match. Quote multi-word values.                                                   |
| `source`     | `created_by_me`, `shared_with_me`                                | Ownership scope. Default: `created_by_me`. Pass both values comma-separated to return owned and shared conversations. |
| `search`     | text                                                             | Full-text search across chat titles, PR titles, PR numbers, and message content. Quote multi-word values.             |

Multiple filters in one query combine with AND logic. `search:` cannot
be combined with `title:`, `pr_title:`, or `pr:`.

## Full-text search

`search:` uses token-based PostgreSQL full-text search:

- Case-insensitive whole-word matching with AND semantics. Quoted
  phrases, `OR`, and `-` negation follow
  [`websearch_to_tsquery`](https://www.postgresql.org/docs/current/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES)
  rules.
- Message content matches English word stems (`refactor` matches
  `refactoring`) and ignores English stopwords. Titles and PR titles
  do not stem.
- No fuzzy, semantic, or prefix matching.
- Whole-number values also match exact PR numbers.
- A value with no searchable words (punctuation only) returns an empty
  list; an empty value returns HTTP 400.
- Results use the standard chat list ordering (pinned first, then most
  recently updated) and pagination, without match snippets.
- Message content becomes searchable shortly after it is written (background indexing, usually within 10&nbsp;minutes).
  Titles and PR titles are searchable immediately.

## Examples

```sh
# Title substring (case-insensitive)
?q=title:deploy

# Multi-word title (URL-encode the space or use +)
?q=title:my+project

# Unread conversations
?q=has_unread:true

# Conversations that need you, or that failed
?q=status:requires_action,error

# Conversations with a turn in progress
?q=status:running

# Conversations with open or draft PRs
?q=pr_status:open,draft

# Conversations with no pull request, or an open one
?q=pr_status:none,open

# Filter by diff URL (quote values containing colons)
?q=diff_url:"https://github.com/coder/coder/pull/123"

# Combine filters
?q=title:refactor+has_unread:true+pr_status:merged

# Conversations linked to PR #42
?q=pr:42

# Conversations for a specific repository
?q=repo:coder/coder

# Conversations with a specific PR title
?q=pr_title:"fix auth bug"

# Conversations shared with you, plus your own
?q=source:created_by_me,shared_with_me

# Full-text search across titles, PR titles, and messages
?q=search:"kubernetes restart"

# Combine full-text search with other filters
?q=search:refactor+pr_status:open
```

## Notes

- `status:waiting` is an idle conversation, `status:running` is a turn in progress, and `status:interrupting` is a turn being stopped.
- `status:requires_action` means the agent needs you before it can continue, and `status:error` means the turn failed.
- `title:`, `repo:`, and `pr_title:` use ILIKE matching. `%` and `_` act as wildcards.
- `pr_status:draft` means the PR is open **and** marked as a draft.
  `pr_status:open` means the PR is open and not a draft.
- `pr_status:none` matches conversations with no pull request, including those whose linked PR was cleared.
- Conversations without a linked diff status are excluded when `pr`, `repo`, `pr_title`, or any `pr_status` value other than `none` is set. The `repo:` filter also matches chats tracking a branch with no PR.
- Unrecognized keys, bare terms, or combining `search:` with `title:`, `pr_title:`, or `pr:` return HTTP 400 with a validation error.

---

# Licensing & Usage

Source: https://coder.com/docs/ai-coder/agents/licensing-usage

Coder Agents licensing controls concurrent agent activity and Agent Time usage across your deployment.

## Community licenses

Community licenses support up to five concurrently active agents deployment-wide.
Coder doesn't limit how long those agents can run or how many tasks they complete over time.
Agents queue when more than five agents are active at a time.
With this agent pool, individuals and small teams can experiment with Coder Agents at no cost.

## Premium licenses and Agent Hours

A Premium license includes a preset amount of Agent Time.
Agent Time is shared across the deployment, allowing unlimited agents to run concurrently while consuming from a shared pool of purchased working hours.
This usage-based model supports enterprise workloads where large development teams, background automation, and API-triggered tasks can create variable bursts of agent activity.

## Agent Time measurement

Agent Time is the cumulative duration of model invocations that produce Coder Agents chat messages.
Coder measures each invocation from immediately before the request to the model provider opens until the response stream is fully consumed.

Agent Time includes:

- Assistant generation steps in top-level and subagent chats.
- Context compaction (summarization) model calls.
- Model-provider tool execution within a model response.
- The time streamed or spent executing tools before an interrupt, kept on the partial assistant messages.

Agent Time excludes:

- Time spent composing or reviewing messages.
- Time between conversation turns while an agent waits for user input.
- Time a parent agent spends waiting for a subagent, because the subagent records its own model invocations.
- Model calls that don't produce chat messages, such as title generation.
- Failed or retried model calls, which persist no content and record no runtime.
- Client-executed tools and chats handed off to external coding agents, since that work happens outside the control plane.

Coder records Agent Time in milliseconds and sums it across all Coder Agents chats in the deployment.

## Concurrency and usage limits

Coder handles concurrency and usage limits differently depending on the license you use.

### Community concurrency limit

When a Community license deployment reaches its limit of five concurrently active agents, Coder places additional agents in a queue.
When an active agent completes its task, the next queued agent begins its work.

### Agent Hours exhaustion

Coder sends deployment administrators an in-app soft warning as the deployment approaches its maximum allotted Agent Time, so they can purchase additional Agent Time before the concurrency fallback takes effect.

## Agent Time usage reporting

Coder reports Agent Time usage to Tallyman, a Coder-managed server used for billing and reporting.
Coder sends the total Coder Agents runtime consumed per UTC hour, in milliseconds, with your deployment ID.
Coder doesn't send user-identifiable information or additional chat data to Tallyman.
Coder also shares the reported usage with [Metronome](https://metronome.com), a Stripe product and Coder partner for usage-based billing and reporting.

Your Coder deployment must be able to make outbound HTTPS requests to `https://tallyman-prod.coder.com` to report usage.
Coder generates one `hb_agent_runtime_v1` event for each UTC hour shortly after the hour ends, then checks for unpublished events approximately every 17&nbsp;minutes.
In steady state, each hour's usage typically reaches Tallyman within about 25&nbsp;minutes of the hour closing.
You can monitor these requests in `coderd` logs.

A successful request produces a debug log similar to the following example when you enable debug logging with [`CODER_LOG_FILTER=.*`](../../reference/cli/server/index.md#-l---log-filter):

```sh
[debu] published usage events to tallyman accepted=1 rejected=0
```

Coder sends the license JWT and deployment ID as request headers.
The request body contains one `hb_agent_runtime_v1` event for each UTC hour.
The `runtime_ms` value is the total Agent Time recorded during that hour.
Idle hours have a value of `0`.
If the deployment was offline, Coder backfills missed hours for up to seven days, batching up to 100 events per request.
Hours missing beyond seven days aren't reported.

The following example reports 1&nbsp;hour of Agent Time:

```txt
POST /api/v1/events/ingest HTTP/1.1
Host: tallyman-prod.coder.com
Content-Type: application/json
Coder-License-Key: <license-jwt>
Coder-Deployment-ID: 8a4e92f1-3b7c-4d5e-9f12-abc123def456

{
  "events": [
    {
      "id": "hb_agent_runtime_v1:2026-08-18_14:00:00",
      "event_type": "hb_agent_runtime_v1",
      "event_data": {
        "runtime_ms": 3600000
      },
      "created_at": "2026-08-18T14:00:00Z"
    }
  ]
}
```

The event ID contains the start of the UTC hour.
The `created_at` value also identifies the start of that hour, rather than the time when Coder sends the request.
Coder sends raw milliseconds without rounding or converting the value to hours.

A failed request produces a warning similar to the following example:

```sh
[warn] failed to send publish request to tallyman count=1 error="Post \"https://tallyman-prod.coder.com/api/v1/events/ingest\": dial tcp: lookup tallyman-prod.coder.com: no such host"
```

> [!NOTE]
> Air-gapped deployments and deployments with legal restrictions around usage reporting can [contact us](https://coder.com/contact) to discuss alternative methods.

---

# Migrate from the Tasks API to the Chats API

Source: https://coder.com/docs/ai-coder/agents/tasks-to-chats-migration

> [!WARNING]
> Coder Tasks was deprecated in Coder v2.34 and has been removed, including the Tasks API (`/api/v2/tasks`).
> To read about Coder Tasks, use a previous version of the Coder documentation, from a release before v2.36.

The Tasks API (`/api/v2/tasks`) and the
[Chats API](../../reference/api/chats.md) (`/api/v2/chats`) serve similar
goals (programmatic access to AI-powered coding agents) but they differ
significantly in architecture, capabilities, and usage patterns.

This guide walks you through updating your integrations from the Tasks API
to the Chats API.

## When to migrate

Migrate now.
Coder Tasks has been removed, so requests to the Tasks API fail.

If your integrations still call the Tasks API, migrate to the Chats API and [Coder Agents](./index.md).
Coder Agents runs the agent loop in the Coder control plane rather than inside the workspace, and is the supported path going forward.

The two systems are not interchangeable. Tasks and Chats are separate
resources with separate APIs, so plan to update your integrations rather
than expecting a drop-in replacement.

## Key architectural differences

Before mapping individual endpoints, understand the structural changes:

| Aspect                 | Tasks API                                                                        | Chats API                                                  |
|------------------------|----------------------------------------------------------------------------------|------------------------------------------------------------|
| Agent execution        | Agent runs **inside the workspace** (via AgentAPI)                               | Agent loop runs **in the control plane**                   |
| LLM credentials        | Injected into workspace environment                                              | Stored in control plane only; never enters the workspace   |
| Workspace provisioning | You specify a `template_version_id` at creation                                  | The agent auto-selects a template and provisions on demand |
| Template requirements  | Requires `coder_ai_task` resource, `coder_task` data source, and an agent module | Any template with a clear description works                |
| Chat state             | Stored in the workspace (AgentAPI state file)                                    | Persisted in the Coder database                            |
| Conversation model     | Single prompt with optional follow-up input                                      | Multi-turn chat with message history, queuing, and editing |
| Real-time updates      | HTTP polling (`GET .../logs`)                                                    | WebSocket streaming (`GET .../stream`)                     |
| Sub-agents             | Not supported                                                                    | Built-in sub-agent delegation                              |

## Endpoint mapping

The table below maps each Tasks API endpoint to its Chats API equivalent.

| Operation         | Tasks API                                 | Chats API                                                 |
|-------------------|-------------------------------------------|-----------------------------------------------------------|
| List              | `GET /api/v2/tasks`                       | `GET /api/v2/chats`                                       |
| Create            | `POST /api/v2/tasks/{user}`               | `POST /api/v2/chats`                                      |
| Get by ID         | `GET /api/v2/tasks/{user}/{task}`         | `GET /api/v2/chats/{chat}`                                |
| Delete            | `DELETE /api/v2/tasks/{user}/{task}`      | `PATCH /api/v2/chats/{chat}` with `{"archived": true}`    |
| Send follow-up    | `POST /api/v2/tasks/{user}/{task}/send`   | `POST /api/v2/chats/{chat}/messages`                      |
| Update input      | `PATCH /api/v2/tasks/{user}/{task}/input` | `PATCH /api/v2/chats/{chat}/messages/{message}`           |
| Get logs / stream | `GET /api/v2/tasks/{user}/{task}/logs`    | `GET /api/v2/chats/{chat}/stream` (WebSocket)             |
| Pause             | `POST /api/v2/tasks/{user}/{task}/pause`  | `POST /api/v2/chats/{chat}/interrupt`                     |
| Resume            | `POST /api/v2/tasks/{user}/{task}/resume` | `POST /api/v2/chats/{chat}/messages` (send a new message) |
| Watch all         | n/a                                       | `GET /api/v2/chats/watch` (WebSocket)                     |
| Get messages      | n/a                                       | `GET /api/v2/chats/{chat}/messages`                       |
| List models       | n/a                                       | `GET /api/v2/organizations/{organization}/chats/models`   |
| Upload file       | n/a                                       | `POST /api/v2/chats/files`                                |

## Migration steps

### 1. Configure an LLM provider

With Tasks, LLM credentials are injected into the workspace as environment
variables (e.g. `ANTHROPIC_API_KEY`). With Coder Agents, credentials are
configured once in the control plane:

1. Navigate to **Admin settings** > **AI** and select **Providers**.
1. Add or update a provider with its credentials and upstream endpoint, then
   save it.
1. Navigate to **Admin settings** > **AI** > **Models**.
1. Select the correct organization.
1. Add at least one model, and set it as the default.

You no longer pass API keys in template variables or workspace environment. See https://coder.com/docs/ai-coder/agents/getting-started for more information.

### 2. Update task creation calls

**Tasks API**. You specify the user, template version, and a prompt
string:

```sh
# Tasks API: create a task
curl -X POST https://coder.example.com/api/v2/tasks/me \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template_version_id": "<template-version-uuid>",
    "input": "Fix the failing tests in the auth service"
  }'
```

**Chats API**. You send structured content parts. No template or user
path segment is required:

```sh
# Chats API: create a chat
curl -X POST https://coder.example.com/api/v2/chats \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "organization_id": "<your-org-id>",
    "content": [
      {"type": "text", "text": "Fix the failing tests in the auth service"}
    ]
  }'
```

Key differences:

- The `{user}` path parameter is removed. The authenticated user is
  inferred from the session token.
- `organization_id` is required in the request body. The caller must be a
  member of that organization.
- The prompt is now an array of `ChatInputPart` objects (supporting `text`,
  `file`, and `file-reference` types) instead of a plain string.
- `template_version_id` and `template_version_preset_id` are removed. The
  agent selects a template automatically based on the prompt and available
  template descriptions. To pin to a specific workspace, pass
  `workspace_id` instead.
- Optionally pass `model_config_id` to override the default model, or
  `mcp_server_ids` to attach MCP servers.

### 3. Update follow-up message calls

**Tasks API**. Follow-ups use the send endpoint with a plain string:

```sh
# Tasks API: send input
curl -X POST https://coder.example.com/api/v2/tasks/me/my-task/send \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"input": "Now also update the integration tests"}'
```

**Chats API**. Follow-ups use the messages endpoint with content parts:

```sh
# Chats API: send a message
curl -X POST \
  https://coder.example.com/api/v2/chats/$CHAT_ID/messages \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": [
      {"type": "text", "text": "Now also update the integration tests"}
    ]
  }'
```

The Chats API supports message queuing. If the agent is busy, the message
is queued automatically and delivered when the agent finishes its current
step. The response includes a `queued` field indicating whether the message
was delivered immediately or queued.

### 4. Switch from log polling to WebSocket streaming

**Tasks API**. You poll for logs:

```sh
# Tasks API: get logs
curl https://coder.example.com/api/v2/tasks/me/my-task/logs \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN"
```

**Chats API**. You open a one-way WebSocket connection:

```txt
GET wss://coder.example.com/api/v2/chats/{chat}/stream
```

The WebSocket sends JSON envelopes with a `type` field (`"ping"`,
`"data"`, or `"error"`). Data envelopes contain batches of events:

| Event type     | Description                                             |
|----------------|---------------------------------------------------------|
| `message_part` | A chunk of the agent's response (text, tool call, etc.) |
| `message`      | A complete message has been persisted                   |
| `status`       | The chat status changed (e.g. `running` → `waiting`)    |
| `error`        | An error occurred during processing                     |
| `retry`        | The control plane is retrying a failed LLM call         |
| `queue_update` | The queued message list changed                         |

Use `after_id` as a query parameter when reconnecting to skip messages the
client already has.

### 5. Update status handling

Task and chat statuses use different values. The Chats API status set is
defined in `codersdk.ChatStatus`:

| Tasks API status | Chats API status  | Notes                                                                                                               |
|------------------|-------------------|---------------------------------------------------------------------------------------------------------------------|
| `pending`        | `running`         | Chats have no separate queued state; a chat that hasn't been picked up yet reports `running`.                       |
| `running`        | `running`         | Agent is actively working.                                                                                          |
| `complete`       | `waiting`         | Idle. Newly created, finished successfully, or interrupted. This is the default idle state.                         |
| `paused`         | n/a               | The Tasks API pause stops the workspace; the Chats API equivalent is `interrupt` plus separate workspace lifecycle. |
| `failed`         | `error`           | Agent encountered an error.                                                                                         |
| n/a              | `requires_action` | Agent invoked a client-provided tool and is waiting for the result before continuing.                               |
| n/a              | `interrupting`    | An interrupt was requested and the agent is winding down the current run.                                           |

The Chats API uses `waiting` as the default idle state (not `complete`).
A chat enters `waiting` when it is first created (before any message is
queued) and again whenever a run finishes or is interrupted, so treat
`waiting` as "the agent is not currently working" rather than only "the
agent just finished."

### 6. Replace delete with archive

The Tasks API uses `DELETE` to remove a task. The Chats API uses archiving:

```diff
- curl -X DELETE https://coder.example.com/api/v2/tasks/me/my-task \
-   -H "Coder-Session-Token: $CODER_SESSION_TOKEN"

+ curl -X PATCH https://coder.example.com/api/v2/chats/$CHAT_ID \
+   -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
+   -H "Content-Type: application/json" \
+   -d '{"archived": true}'
```

Archived chats can be restored by setting `archived` to `false`.

### 7. Replace pause/resume with interrupt and messaging

**Tasks API**. Pause and resume stop and start the workspace:

```sh
# Tasks API
curl -X POST \
  https://coder.example.com/api/v2/tasks/me/my-task/pause \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN"

curl -X POST \
  https://coder.example.com/api/v2/tasks/me/my-task/resume \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN"
```

**Chats API**. Interrupt stops the current agent loop. Sending a new
message resumes processing:

```sh
# Chats API: interrupt
curl -X POST \
  https://coder.example.com/api/v2/chats/$CHAT_ID/interrupt \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN"

# Chats API: resume by sending a new message
curl -X POST \
  https://coder.example.com/api/v2/chats/$CHAT_ID/messages \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": [
      {"type": "text", "text": "Continue where you left off"}
    ]
  }'
```

In the Tasks API, pausing stops the workspace and frees compute. In the
Chats API, interrupt stops the agent loop in the control plane; the
workspace may remain running. The workspace lifecycle is managed
independently.

### 8. Update GitHub Actions integrations

If you use the
[Create Task Action](https://github.com/coder/create-task-action) GitHub
Action, replace it with the dedicated
[`coder/create-agent-chat-action`](https://github.com/coder/create-agent-chat-action).
It handles the API call, the GitHub user lookup, and the optional issue
comment, so most existing workflows can swap one `uses:` line and rename
a few inputs.

We are actively shipping new features for `create-agent-chat-action`, so
pin to a major version (for example `@v0`) and watch the
[releases](https://github.com/coder/create-agent-chat-action/releases) for
updates.

```diff
# .github/workflows/triage-bug.yaml
jobs:
  coder-create-task:
    runs-on: ubuntu-latest
    if: github.event.label.name == 'coder'
    steps:
-     - name: Coder Create Task
-       uses: coder/create-task-action@v0
-       with:
-         coder-url: ${{ secrets.CODER_URL }}
-         coder-token: ${{ secrets.CODER_TOKEN }}
-         coder-organization: "default"
-         coder-template-name: "my-template"
-         coder-task-name-prefix: "gh-task"
-         coder-task-prompt: >-
-           Use the gh CLI to read
-           ${{ github.event.issue.html_url }},
-           fix the issue, and create a PR.
-         github-user-id: ${{ github.event.sender.id }}
-         github-issue-url: ${{ github.event.issue.html_url }}
-         github-token: ${{ github.token }}
-         comment-on-issue: true
+     - name: Coder Create Agent Chat
+       uses: coder/create-agent-chat-action@v0
+       with:
+         coder-url: ${{ secrets.CODER_URL }}
+         coder-token: ${{ secrets.CODER_TOKEN }}
+         chat-prompt: >-
+           Use the gh CLI to read
+           ${{ github.event.issue.html_url }},
+           fix the issue, and create a PR.
+         github-url: ${{ github.event.issue.html_url }}
+         github-token: ${{ github.token }}
+         comment-on-issue: true
```

Key differences from the Tasks GHA:

- No `coder-template-name` or `coder-task-name-prefix`. The agent
  auto-provisions a workspace; pass `workspace-id` if you want to pin to
  an existing workspace instead.
- The prompt input is renamed from `coder-task-prompt` to `chat-prompt`.
- LLM credentials are no longer passed through the template. They are
  configured in the Coder control plane.
- No user mapping: the Tasks GHA's `github-user-id` input has no equivalent, because the chat is always owned by the user the `coder-token` belongs to and the Chats API has no owner override.

See the
[action README](https://github.com/coder/create-agent-chat-action#inputs)
for the full input and output reference, including the `existing-chat-id`
input for sending follow-up messages on a previous chat.

## Template recommendations

<!-- NEEDS REVIEW: This section contains initial recommendations based on
     the current Coder Agents architecture. Platform teams should validate
     these against their own deployment patterns before adopting them. -->

> [!NOTE]
> This section contains recommendations that may evolve as Coder Agents
> matures. Review these against your deployment requirements.

With Coder Tasks, every task-capable template requires specific Terraform
resources (`coder_ai_task`, `coder_task`, agent modules, and LLM API
keys). With Coder Agents, templates no longer need any of these. The
agent runs in the control plane and treats the workspace as plain compute.

However, **we still recommend creating dedicated templates for agent
workloads** rather than reusing your standard developer templates
unchanged. The reasons are different from Tasks, but the principle holds:

### Why dedicated agent templates still matter

- **Network boundaries.** Agent workspaces inherit whatever network access
  the template allows. Because the agent does not need outbound access to
  LLM providers (that happens in the control plane), you can lock down
  agent templates to only reach the Coder control plane and your git
  provider. Standard developer templates typically allow broader access.
- **No IDE tooling overhead.** The agent connects via the workspace
  daemon's HTTP API, not through VS Code or JetBrains. Removing IDE
  extensions, desktop environments, and similar tooling from agent
  templates reduces image size and startup time.
- **Scoped credentials.** Agent workloads may warrant more restrictive
  credentials than interactive developer sessions. A dedicated template
  lets you provide a separate, narrower-scoped git token or service
  account without affecting your developers' workflow.
- **Cost control.** Agent workspaces can often use smaller compute
  resources than developer workspaces since they don't need to run IDEs,
  language servers, or other interactive tooling. A dedicated template lets
  you right-size the infrastructure.

### What to include in agent templates

<!-- TODO: Expand this section with concrete Terraform examples once
     template patterns stabilize. -->

- **Clear descriptions.** The agent selects templates by reading names and
  descriptions. Include the target language, framework, repository, and
  type of work. For example: *"Python backend services for the payments
  repo. Includes Poetry, Python 3.12, and PostgreSQL."*
- **Pre-installed dependencies.** Language runtimes, build tools, `git`,
  and project-specific dependencies should be baked into the image. Time
  the agent spends installing tools is time not spent on the task.
- **Git configuration.** Ensure `git` is configured with credentials and
  author information so the agent can commit and push without additional
  setup.
- **Minimal parameters.** Use sensible defaults so the agent can provision
  workspaces without guessing. Avoid required parameters with opaque
  identifiers.

### What to remove from migrated task templates

If you are converting an existing task template for use with Coder Agents,
you can safely remove the Tasks-specific Terraform resources. They are
unused when the chat is driven by the Chats API:

```diff
  terraform {
    required_providers {
      coder = {
        source  = "coder/coder"
-       version = ">= 2.13"
+       version = ">= 2.13"
      }
    }
  }

- data "coder_task" "me" {}
-
- resource "coder_ai_task" "task" {
-   app_id = module.claude-code.task_app_id
- }
-
- module "claude-code" {
-   source         = "registry.coder.com/coder/claude-code/coder"
-   version        = "4.0.0"
-   agent_id       = coder_agent.main.id
-   ai_prompt      = data.coder_task.me.prompt
-   claude_api_key = var.anthropic_api_key
- }
-
- variable "anthropic_api_key" {
-   type        = string
-   description = "Anthropic API key"
-   sensitive   = true
- }

  resource "coder_agent" "main" {
    os   = "linux"
    arch = "amd64"
+   # No agent modules, no AgentAPI, no LLM keys needed.
+   # The Coder Agents control plane handles the agent loop.
  }
```

> [!IMPORTANT]
> Remove the Tasks-specific Terraform when you upgrade.
> Tasks and Chats can no longer run side by side: Coder no longer injects `CODER_TASK_ID` or `CODER_TASK_PROMPT`, so builds of a template that keeps the `coder_task` data source can no longer populate it.

See
[Template Optimization](./platform-controls/template-optimization.md)
for the full guide on writing discoverable descriptions, configuring
network boundaries, scoping credentials, and pre-installing dependencies.

### Pre-creating a workspace for deterministic results

Letting the agent pick a template and provision a workspace works well
for exploratory chats. If your workflow requires deterministic results like:

- Automations
- Recurring processes
- Generally any case that needs a known reproducible environment

pre-create the workspace yourself and attach it when you create the chat.

The pattern is two API calls:

1. Create a workspace from a specific template via
   [`POST /api/v2/users/{user}/workspaces`](../../reference/api/workspaces.md#create-user-workspace).
   You control the template, the version, and any rich parameters.
2. Create the chat with `workspace_id` set to the workspace you just
   created. The agent runs against that workspace instead of selecting
   one heuristically.

```sh
# 1. Provision the workspace from the exact template you want.
WORKSPACE_ID=$(curl -s -X POST \
  https://coder.example.com/api/v2/users/me/workspaces \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "template_id": "<your-agent-template-uuid>",
    "name": "agent-run-${GITHUB_RUN_ID}"
  }' | jq -r '.id')

# 2. Create the chat bound to that workspace.
curl -s -X POST https://coder.example.com/api/v2/chats \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{
    \"organization_id\": \"<your-org-id>\",
    \"workspace_id\": \"$WORKSPACE_ID\",
    \"content\": [
      {\"type\": \"text\", \"text\": \"Fix the failing tests in the auth service\"}
    ]
  }"
```

This pattern is the closest analogue to the Tasks API behavior of
`template_version_id` plus `coder-template-name`: you decide which
template runs, the agent decides what to do inside it. The same approach
works from the
[`coder/create-agent-chat-action`](https://github.com/coder/create-agent-chat-action)
GHA, which exposes the same pin via its `workspace-id` input.

## How to test your migration

After completing the migration steps above, walk through these checks to
confirm the Chats API integration is working end-to-end.

### 1. Confirm LLM provider connectivity

List the available models in an organization to verify at least one provider is configured and reachable:

```sh
curl -s https://coder.example.com/api/v2/organizations/$CODER_ORGANIZATION/chats/models \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" | jq '.models[].display_name'
```

If this returns an empty list or an error, revisit
[Step 1: Configure an LLM provider](#1-configure-an-llm-provider).

### 2. Create a chat and confirm the response

Create a simple chat that does not require a workspace:

```sh
curl -s -X POST https://coder.example.com/api/v2/chats \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": [{"type": "text", "text": "What is 2 + 2?"}]
  }' | jq '{id, status, title}'
```

You should receive a `Chat` object with `status` set to `"running"`,
since new chats begin processing immediately. Save the `id` for
subsequent steps.

### 3. Stream the response

Open a WebSocket connection to verify the agent processes the prompt and
returns a response. Using [websocat](https://github.com/vi/websocat):

```sh
websocat -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  "wss://coder.example.com/api/v2/chats/$CHAT_ID/stream"
```

You should see JSON envelopes with `"type": "data"` containing
`message_part` and `status` events. The chat should eventually reach
`"waiting"` status, indicating the agent completed its response.

### 4. Send a follow-up message

Verify multi-turn conversation works:

```sh
curl -s -X POST \
  "https://coder.example.com/api/v2/chats/$CHAT_ID/messages" \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "content": [{"type": "text", "text": "Now multiply that by 10"}]
  }' | jq '{queued}'
```

The response should include `"queued": false` (delivered immediately) or
`"queued": true` (agent was busy. The message is queued and will be
processed next).

### 5. Test workspace provisioning

Create a workspace from your converted agent template through the
standard Coder UI, then attach it to a new chat from the chat composer:

1. In the Coder dashboard, create a workspace from the agent template
   you migrated.
2. Open **Agents** and start a new chat.
3. In the composer, use the workspace picker to attach the workspace you
   just created.
4. Send a prompt that exercises the workspace, for example: *"List the
   files in the root directory of this workspace."*

The response stream should show the agent invoking workspace tools (such
as `execute`) against the attached workspace. After the chat finishes,
verify the chat is bound to the workspace via the API:

```sh
curl -s "https://coder.example.com/api/v2/chats/$CHAT_ID" \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" | jq '{workspace_id, status}'
```

A `workspace_id` matching the workspace you attached confirms the chat
is driving that workspace end-to-end. Auto-provisioning from the chat
flow is also supported but is easier to verify once the manual-attach
path is working.

### 6. Verify interrupt works

Start a long-running chat and interrupt it:

```sh
curl -s -X POST \
  "https://coder.example.com/api/v2/chats/$CHAT_ID/interrupt" \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN"
```

Then confirm the chat status returns to `"waiting"`:

```sh
curl -s "https://coder.example.com/api/v2/chats/$CHAT_ID" \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" | jq '.status'
```

### 7. Validate archive and restore

```sh
# Archive
curl -s -X PATCH \
  "https://coder.example.com/api/v2/chats/$CHAT_ID" \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"archived": true}'

# Confirm it no longer appears in the default list
curl -s "https://coder.example.com/api/v2/chats" \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  | jq --arg id "$CHAT_ID" '[.[] | select(.id == $id)] | length'
# Should return 0

# Restore
curl -s -X PATCH \
  "https://coder.example.com/api/v2/chats/$CHAT_ID" \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"archived": false}'
```

### Quick checklist

Use this checklist to confirm each part of your integration:

- [ ] At least one LLM model is configured in the organization and returned by `/organizations/{organization}/chats/models`
- [ ] `POST /chats` creates a chat and returns a valid `Chat` object
- [ ] WebSocket stream at `/chats/{chat}/stream` delivers events
- [ ] Follow-up messages via `/chats/{chat}/messages` are accepted
- [ ] Chat attached to a workspace from the converted template runs
      tools against that workspace
- [ ] `POST /chats/{chat}/interrupt` stops the agent and returns to `waiting`
- [ ] Archive and restore via `PATCH /chats/{chat}` works
- [ ] (If applicable) GitHub Actions workflow creates chats successfully

## Features available only in the Chats API

The Chats API includes capabilities that have no equivalent in the Tasks
API:

| Feature                              | Description                                                                                           |
|--------------------------------------|-------------------------------------------------------------------------------------------------------|
| **WebSocket streaming**              | Real-time event stream via `GET /chats/{chat}/stream` instead of HTTP polling                         |
| **Watch all chats**                  | `GET /chats/watch` pushes events for all chats owned by the user                                      |
| **Message editing**                  | `PATCH /chats/{chat}/messages/{message}` to edit a sent message and re-process                        |
| **Message queuing**                  | Follow-up messages are automatically queued when the agent is busy                                    |
| **File uploads**                     | Attach images via `POST /chats/files` and reference them in messages                                  |
| **Model selection**                  | `GET /organizations/{organization}/chats/models` to discover models; override per-chat or per-message |
| **MCP server attachment**            | Attach MCP servers to a chat for tool augmentation                                                    |
| **Labels**                           | Key-value metadata on chats for filtering (`label` query parameter)                                   |
| **Sub-agents**                       | Agent can spawn child agents for parallel work                                                        |
| **Diff/PR tracking**                 | `GET /chats/{chat}/diff` returns change tracking and PR metadata                                      |
| **Title generation**                 | `POST /chats/{chat}/title/propose` returns a suggested title                                          |
| **Pinning**                          | Pin and reorder chats via the `pin_order` field                                                       |
| **Automatic workspace provisioning** | Created for workspace access or to obtain missing tools, skills, MCP integrations, or context         |

## Response schema changes

The Tasks API returns a `Task` object with workspace-centric fields. The
Chats API returns a `Chat` object with conversation-centric fields:

| Tasks API field    | Chats API equivalent                          | Notes                                                            |
|--------------------|-----------------------------------------------|------------------------------------------------------------------|
| `id`               | `id`                                          | Both are UUIDs                                                   |
| `initial_prompt`   | First message in `GET /chats/{chat}/messages` | Prompt is a message, not a top-level field                       |
| `display_name`     | `title`                                       | Auto-generated or set via `PATCH`                                |
| `status`           | `status`                                      | Different enum values (see status table above)                   |
| `current_state`    | Latest `status` event from the stream         | No equivalent top-level field                                    |
| `workspace_id`     | `workspace_id`                                | Nullable in Chats. May be `null` if no workspace was provisioned |
| `workspace_status` | n/a                                           | Manage workspace lifecycle separately                            |
| `template_id`      | n/a                                           | Not exposed; the agent selects templates internally              |
| `owner_id`         | `owner_id`                                    | Same concept                                                     |
| `name`             | n/a                                           | Chats use `id` for identification, not human-readable names      |

## CLI changes

The Tasks CLI (`coder task`) was removed, and Coder does not ship an interactive Coder Agents TUI.
Use the web UI for interactive chat and direct API calls for automation.
The table below maps the removed commands to their Chats API equivalents.

| Removed Tasks CLI   | Chats equivalent                       |
|---------------------|----------------------------------------|
| `coder task create` | Web UI or `POST /chats`                |
| `coder task list`   | Web UI or `GET /chats`                 |
| `coder task logs`   | `GET /chats/{chat}/stream` (WebSocket) |
| `coder task pause`  | `POST /chats/{chat}/interrupt`         |
| `coder task resume` | Send a follow-up message to the chat   |

---

# Agent Relay

Source: https://coder.com/docs/ai-coder/agent-relay

Agent Relay connects a cloud-hosted AI coding agent's hosted sessions to self-hosted [Coder workspaces](../../user-guides/workspace-management.md).
Developers keep the cloud agent's client and workflow.
Coder provides the workspace where the agent's tool calls run.

<img src="../../images/guides/ai-agents/agent-relay-stack.png" alt="Agent Relay architecture diagram" style="border: none;">

## How Agent Relay works

Agent Relay watches for pending agent sessions from a supported provider.
When a session starts, Agent Relay provisions a Coder workspace from a mapped template and connects the session to a worker process inside that workspace.
The worker executes the agent's tool calls, such as reading files, running commands, and using development tools, against the resources available in that workspace.
Agent Relay manages the workspace for the life of the session and tears it down when the session ends.

<img src="../../images/guides/ai-agents/agent-relay-workflow.png" alt="Agent Relay workflow diagram" style="border: none;">

## What Agent Relay is and isn't

Agent Relay changes where a cloud agent's tool calls execute.
It doesn't change where the agent's orchestration or AI inference run.
Those stay with the cloud provider.

Agent Relay is not:

- A replacement for [Coder Agents](../agents/index.md), Coder's own AI workflow infrastructure that runs its native agent loop inside the Coder control plane and calls out to your configured LLM provider for inference.
- A proxy or observability layer for a provider's AI inference.
  Coder has no access to model selection or token usage for sessions that run through Agent Relay.
- A self-hosted deployment of a cloud provider's control plane.
  The provider's orchestration stays cloud-hosted.

## Business value

- Developers keep using the cloud agent client and workflow they already know.
- Platform and security teams control the infrastructure where agent sessions execute and which internal resources those sessions can reach.
- Agent sessions run in workspaces built from the same templates, networking, and governance controls as the rest of your Coder deployment.
- Each session gets its own workspace, provisioned on demand and deleted when the session ends.

## Current state

Agent Relay is in [early access](../../reference/feature-stages.md#early-access-features) and is in closed preview with select customers.

The daemon is distributed as a public container image and Helm chart:

- Image: `ghcr.io/coder/agent-relay`, tagged `X.Y.Z`, `X.Y`, and `latest` for each release.
- Helm chart: `oci://ghcr.io/coder/chart/coder-agent-relay`, versioned to match the image it deploys.

Configuring a relay requires a provider credential and a compatible template, so talk to your account team before you deploy it.

## Supported providers

[Cursor](./cursor.md) and [Claude Code](./claude-code.md) are the providers Agent Relay supports.
Coder built Agent Relay to support additional cloud-hosted agent providers as they add support for self-hosted execution.

## Get started

If you want access to Agent Relay or want updates on the support status for your cloud-hosted agent provider of choice, talk to your [Coder account team](https://coder.com/contact) or email [sales@coder.com](mailto:sales@coder.com).

## Learn more

- [Agent Relay for Cursor](./cursor.md)
- [Agent Relay for Claude Code](./claude-code.md)
- [Coder Agents](../agents/index.md)
- [Architecture](../../install/plan/architecture.md)

---

# Agent Relay for Cursor

Source: https://coder.com/docs/ai-coder/agent-relay/cursor

> [!NOTE]
> Agent Relay for Cursor is in [early access](../../reference/feature-stages.md#early-access-features) and is currently in closed preview with select customers.

[Agent Relay](./index.md) connects [Cursor Cloud Agents](https://cursor.com/cloud) to self-hosted Coder workspaces.
Cursor also refers to this self-hosted worker model as [self-hosted machines](https://cursor.com/docs/cloud-agent/self-hosted).
Developers keep using the Cursor client and cloud agent workflow they already know.
The agent's tool calls run inside a Coder workspace on infrastructure you control instead of a Cursor-managed environment.

Cursor's agent orchestration and AI inference remain cloud-hosted.
Coder doesn't proxy or observe model inference.
Coder provides the workspace where the agent executes, and logs that correlate the Cursor session and user to that workspace.

## How it works

1. A developer selects a Cursor worker pool mapped to a Coder organization and workspace template, then starts a Cursor agent session.
1. Agent Relay claims the pending Cursor request and asks the Coder control plane to provision a workspace from the mapped template for that user.
1. A Cursor worker process inside the workspace connects to the corresponding Cursor cloud session and executes the agent's tool calls.
1. When the session ends, Agent Relay manages workspace teardown.

Each Cursor agent session gets its own ephemeral workspace.

## Requirements

- A licensed Coder deployment
- A Cursor Enterprise plan

## Get started

Talk to your [Coder account team](https://coder.com/contact) or email [sales@coder.com](mailto:sales@coder.com) to get access to Agent Relay for Cursor.

## Learn more

- [Agent Relay](./index.md)
- [Architecture](../../install/plan/architecture.md)

---

# Agent Relay for Claude Code

Source: https://coder.com/docs/ai-coder/agent-relay/claude-code

> [!NOTE]
> Agent Relay for Claude Code is in [early access](../../reference/feature-stages.md#early-access-features) and is currently in closed preview with select customers.

[Agent Relay](./index.md) connects [Claude Code](https://claude.ai/code) sessions to self-hosted Coder workspaces.
Anthropic calls this self-hosted worker model [self-hosted environments](https://code.claude.com/docs/en/self-hosted-environments).
Developers keep using the claude.ai/code or Claude Desktop client and workflow they already know.
The Claude Code runner's tool calls run inside a Coder workspace on infrastructure you control instead of an Anthropic-managed environment.

Anthropic's agent orchestration and AI inference remain cloud-hosted.
Coder doesn't proxy or observe model inference.
Coder provides the workspace where the runner executes and logs that correlate the Claude Code session and user to that workspace.

## How it works

1. A developer starts a Claude Code session at claude.ai/code or in Claude Desktop, targeting a self-hosted runner pool mapped to a Coder organization and workspace template.
1. Agent Relay claims the pending work order for that session and asks the Coder control plane to provision a workspace from the mapped template for that user.
1. A Claude Code self-hosted runner inside the workspace registers with the corresponding Claude Code session and executes the agent's tool calls.
1. When the session ends, Agent Relay manages workspace teardown.

Each Claude Code session gets its own ephemeral workspace.

## Requirements

- A licensed Coder deployment
- An Anthropic Team or Enterprise plan

Self-hosted environments are in public beta on these plans.
Refer to Anthropic's [self-hosted environment documentation](https://code.claude.com/docs/en/self-hosted-environments) for details.

## Get started

Talk to your [Coder account team](https://coder.com/contact) or email [sales@coder.com](mailto:sales@coder.com) to get access to Agent Relay for Claude Code.

## Learn more

- [Agent Relay](./index.md)
- [Architecture](../../install/plan/architecture.md)

---

# AI Governance

Source: https://coder.com/docs/ai-coder/ai-governance

Coder Workspaces already lets teams run AI tools like
[Cursor](https://registry.coder.com/modules/coder/cursor) and
[Claude Code](https://registry.coder.com/modules/coder/claude-code) inside their
development environments. As adoption grows, many enterprises also need
observability, management, and policy controls to support secure and auditable
AI rollouts.

AI Governance is included with a Premium license. Each Premium user gets access
to a set of features that help organizations safely roll out AI tooling at scale:

- [AI Gateway](./ai-gateway/index.md): LLM gateway to audit AI sessions, central
  MCP server management, and policy enforcement
- [Agent Firewall](./agent-firewall/index.md): Process-level firewalls for
  agents, restricting which domains can be accessed by AI agents

> [!NOTE]
> AI Gateway and Agent Firewall require a Premium license.
> Community deployments cannot access these features.

## Who should use AI Governance

AI Governance is for teams that want to extend the Coder platform to support
AI-powered IDEs and coding agents in a controlled, observable way.

It's a good fit if you're:

- Rolling out AI-powered IDEs like Cursor and AI coding agents like Claude Code
  across teams
- Looking to centrally observe, audit, and govern AI activity in Coder
  Workspaces
- Managing AI workflows against sensitive or regulated codebases

If you already use other AI Governance tools, such as third-party LLM gateways
or vendor-managed policies, you can continue using them. Coder Workspaces can
still serve as the backend for development environments and AI workflows, with
or without Coder's AI Governance features.

## Use cases for AI Governance

Organizations adopting AI coding tools at scale often encounter operational and
security challenges that traditional developer tooling doesn't address.

### Audit AI activity across teams

Without centralized monitoring, teams have no way to understand how AI tools are
being used across the organization. AI Gateway provides audit trails of prompts,
token usage, and tool invocations, giving administrators insight into AI
adoption patterns and potential issues.

### Restrict agent network access

AI agents can make arbitrary network requests, potentially accessing unauthorized services or exfiltrating data.
Agent Firewall enforces process-level policies that restrict which domains agents can reach and what actions they can perform,
preventing unintended data exposure.

### Centralize API key management

Managing individual API keys for AI providers across hundreds of developers
creates security risks and administrative overhead. AI Gateway centralizes
authentication so users authenticate through Coder, eliminating the need to
distribute and rotate provider API keys.

### Standardize MCP tools and servers

Different teams may use different MCP servers and tools with varying security
postures. AI Gateway enables centralized MCP administration, allowing
organizations to define approved tools and servers that all users can access.

### Measure AI adoption and spend

Without usage data, it's hard to justify AI tooling investments or identify
high-leverage use cases. AI Gateway captures metrics on token spend, adoption
rates, and usage patterns to inform decisions about AI strategy.

## GA status and availability

Starting with Coder v2.30 (February 2026), AI Gateway and Agent Firewall are
generally available as part of AI Governance.

To learn more about AI Governance, pricing, or trial options, reach out to your
[Coder account team](https://coder.com/contact/sales).

---

# Agent Firewall

Source: https://coder.com/docs/ai-coder/agent-firewall

Agent Firewall is a process-level firewall that restricts and audits what
autonomous programs, such as AI agents, can access and use.

![Screenshot of Agent Firewall blocking a process](../../images/guides/ai-agents/boundary.png)Example
of Agent Firewall blocking a process.

> [!NOTE]
> Agent Firewall is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.
>
> Agent Firewall was previously known as "Agent Boundaries". Some
> configuration options and internal references still use the old name
> and will be updated in a future release.

## Supported Agents

Agent Firewall supports the securing of any terminal-based agent, including
your own custom agents.

## Features

Agent Firewall offers network policy enforcement, which blocks domains and HTTP
verbs to prevent exfiltration, and writes logs to the workspace.

Agent Firewall also streams audit logs to Coder's control plane for centralized
monitoring of HTTP requests.

<a id="getting-started-with-agent-firewall"></a>

## Get started with Agent Firewall

The easiest way to use Agent Firewall is through the
[agent-firewall module](https://registry.coder.com/modules/coder/agent-firewall). It
can also be ran directly in the terminal by installing the
[CLI](https://github.com/coder/boundary).

## Configuration

> [!NOTE]
> For information about version requirements and compatibility, see the [Version Requirements](./version.md) documentation.

Agent Firewall is configured using a `config.yaml` file. This allows you to
maintain allow lists and share detailed policies with teammates.

In your Terraform module, install Agent Firewall with minimal configuration:

```tf
module "agent-firewall" {
  source   = "registry.coder.com/coder/agent-firewall/coder"
  version  = "0.0.1"
  agent_id = coder_agent.main.id
}
```

To use a custom policy, pass it inline via `agent_firewall_config`, below is an example of minimal configuration for Claude Code module:

```tf
module "agent-firewall" {
  source   = "registry.coder.com/coder/agent-firewall/coder"
  version  = "0.0.1"
  agent_id = coder_agent.main.id

  agent_firewall_config = <<-YAML
    allowlist:
      - "domain=coder.example.com" # Required - use your Coder deployment domain
      - "domain=api.anthropic.com" # Required - API endpoint for Claude
      - "domain=statsig.anthropic.com" # Required - Feature flags and analytics
      - "domain=claude.ai" # Recommended - WebFetch/WebSearch features
      - "domain=*.sentry.io" # Recommended - Error tracking (helps Anthropic fix bugs)
    jail_type: nsjail
    log_dir: /tmp/boundary_logs
    proxy_port: 8087
    log_level: warn
  YAML
}
```

For examples of wrapping an agent or process such as Claude Code with Agent
Firewall, see the
[agent-firewall module README](https://registry.coder.com/modules/coder/agent-firewall#with-claude-code).

For a basic recommendation of what to allow for agents, see the
[Anthropic documentation on default allowed domains](https://code.claude.com/docs/en/claude-code-on-the-web#default-allowed-domains).
For a comprehensive example of a production Agent Firewall configuration, see
the
[Coder dogfood policy example](../../../dogfood/coder/boundary-config.yaml).

To load the policy from a `config.yaml` file in your template directory instead,
pass it via `agent_firewall_config`. The module writes the config to the workspace
and exposes the resolved path via `agent_firewall_config_path`, so everyone who
launches Agent Firewall manually inside the workspace picks up the same
configuration without extra flags. This is especially convenient for managing
extensive allow lists in version control.

```tf
module "agent-firewall" {
  source   = "registry.coder.com/coder/agent-firewall/coder"
  version  = "0.0.1"
  agent_id = coder_agent.main.id

  agent_firewall_config = file("${path.module}/config.yaml")
}
```

### Configuration Parameters

- `allowlist` defines the URLs that the agent can access, in addition to the
  default URLs required for the agent to work. Rules use the format
  `"key=value [key=value ...]"`:
  - `domain=github.com` - allows the domain and all its subdomains
  - `domain=*.github.com` - allows only subdomains (the specific domain is
    excluded)
  - `method=GET,HEAD domain=api.github.com` - allows specific HTTP methods for a
    domain
  - `method=POST domain=api.example.com path=/users,/posts` - allows specific
    methods, domain, and paths
  - `path=/api/v1/*,/api/v2/*` - allows specific URL paths
- `jail_type` selects the isolation backend. Valid values: `nsjail` (default),
  `landjail`. See [Jail Types](#jail-types) for a detailed comparison.
- `log_dir` defines where boundary writes log files.
- `log_level` defines the verbosity at which requests are logged. Agent
  Firewall uses the following verbosity levels:
  - `WARN`: logs only requests that have been blocked by Agent Firewall
  - `INFO`: logs all requests at a high level
  - `DEBUG`: logs all requests in detail
- `no_user_namespace` disables creation of a user namespace inside the jail.
  Enable this in restricted environments that disallow user namespaces, such
  as Bottlerocket nodes in EKS auto-mode. Only applies to the `nsjail` jail
  type.
- `proxy_port` defines the port used by the HTTP proxy. Default: `8080`.
- `use_real_dns` uses the host's real DNS resolver inside the jail instead of
  the built-in dummy DNS server. This allows DNS resolution for non-proxied
  traffic but permits DNS-based data exfiltration. Default: `false`.

For detailed information about the rules engine and how to construct allowlist
rules, see the [rules engine documentation](./rules-engine.md).

You can also run Agent Firewall directly in your workspace and configure it
per template. You can do so by installing the
[binary](https://github.com/coder/boundary) into the workspace image or at
start-up. You can do so with the following command:

```sh
curl -fsSL https://raw.githubusercontent.com/coder/boundary/main/install.sh | bash
```

When running the binary directly, Agent Firewall reads `config.yaml` from
`~/.config/coder_boundary/` automatically.

## Jail Types

Agent Firewall supports two different jail types for process isolation, each
with different characteristics and requirements:

1. **nsjail** - Uses Linux namespaces for isolation. This is the default jail
   type and provides network namespace isolation. See
   [nsjail documentation](./nsjail/index.md) for detailed information about runtime
   requirements and Docker configuration.

2. **landjail** - Uses Landlock V4 for network isolation. This provides network
   isolation through the Landlock Linux Security Module (LSM) without requiring
   network namespace capabilities. See [landjail documentation](./landjail.md)
   for implementation details.

The choice of jail type depends on your security requirements, available Linux
capabilities, and runtime environment. Both nsjail and landjail provide network
isolation, but they use different underlying mechanisms. nsjail uses Linux
namespaces, while landjail uses Landlock V4. Landjail may be preferred in
environments where namespace capabilities are limited or unavailable.

## Implementation Comparison: Namespaces+iptables vs Landlock V4

| Aspect                        | Namespace Jail (Namespaces + veth-pair + iptables)                                | Landlock V4 Jail                                                        |
|-------------------------------|-----------------------------------------------------------------------------------|-------------------------------------------------------------------------|
| **Privileges**                | Requires `CAP_NET_ADMIN`                                                          | ✅ No special capabilities required                                      |
| **Docker seccomp**            | ❌ Requires seccomp profile modifications or sysbox-runc                           | ✅ Works without seccomp changes                                         |
| **Kernel requirements**       | Linux 3.8+ (widely available)                                                     | ❌ Linux 6.7+ (very new, limited adoption)                               |
| **Bypass resistance**         | ✅ Strong - transparent interception prevents bypass                               | ❌ **Medium - can bypass by connecting to `evil.com:<HTTP_PROXY_PORT>`** |
| **Process isolation**         | ✅ PID namespace (processes can't see/kill others); **implementation in-progress** | ❌ No PID namespace (agent can kill other processes)                     |
| **Non-TCP traffic control**   | ✅ Can block/control UDP via iptables; **implementation in-progress**              | ❌ No control over UDP (data can leak via UDP)                           |
| **Application compatibility** | ✅ Works with ANY application (transparent interception)                           | ❌ Tools without `HTTP_PROXY` support will be blocked                    |

## Audit Logs

Agent Firewall streams audit logs to the Coder control plane, providing
centralized visibility into HTTP requests made within workspaces—whether from AI
agents or ad-hoc commands run with `boundary`.

Audit logs are independent of application logs:

- **Audit logs** record Agent Firewall's policy decisions: whether each HTTP
  request was allowed or denied based on the allowlist rules. These are always
  sent to the control plane regardless of Agent Firewall's configured log
  level.
- **Application logs** are Agent Firewall's operational logs written locally to
  the workspace. These include startup messages, internal errors, and debugging
  information controlled by the `log_level` setting.

For example, if a request to `api.example.com` is allowed by Agent Firewall
but the remote server returns a 500 error, the audit log records
`decision=allow` because Agent Firewall permitted the request. The HTTP
response status is not tracked in audit logs.

> [!NOTE]
> Requires Coder v2.30+ and Agent Firewall v0.5.2+.

### Audit Log Contents

Each Agent Firewall audit log entry includes:

| Field                 | Description                                                                             |
|-----------------------|-----------------------------------------------------------------------------------------|
| `decision`            | Whether the request was allowed (`allow`) or blocked (`deny`)                           |
| `workspace_id`        | The UUID of the workspace where the request originated                                  |
| `workspace_name`      | The name of the workspace where the request originated                                  |
| `owner`               | The owner of the workspace where the request originated                                 |
| `template_id`         | The UUID of the template that the workspace was created from                            |
| `template_version_id` | The UUID of the template version used by the current workspace build                    |
| `http_method`         | The HTTP method used (GET, POST, PUT, DELETE, etc.)                                     |
| `http_url`            | The fully qualified URL that was requested                                              |
| `event_time`          | Timestamp when boundary processed the request (RFC3339 format)                          |
| `matched_rule`        | The allowlist rule that permitted the request (only present when `decision` is `allow`) |

<a id="viewing-audit-logs"></a>

### View audit logs

Agent Firewall audit logs are emitted as structured log entries from the Coder
server. You can collect and analyze these logs using any log aggregation system
such as Grafana Loki.

Example of an allowed request (assuming stderr):

```console
2026-01-16 00:11:40.564 [info]  coderd.agentrpc: boundary_request owner=joe  workspace_name=some-task-c88d agent_name=dev  decision=allow  workspace_id=f2bd4e9f-7e27-49fc-961e-be4d1c2aa987  http_method=GET http_url=https://coder.example.com  event_time=2026-01-16T00:11:39.388607657Z  matched_rule=domain=coder.example.com request_id=9f30d667-1fc9-47ba-b9e5-8eac46e0abef trace=478b2b45577307c4fd1bcfc64fad6ffb span=9ece4bc70c311edb
```

---

# nsjail jail type

Source: https://coder.com/docs/ai-coder/agent-firewall/nsjail

> [!NOTE]
> Agent Firewall is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

nsjail is Agent Firewall's default jail type that uses Linux namespaces to
provide process isolation. It creates unprivileged network namespaces to control
and monitor network access for processes running under Boundary.

**Running on Docker, Kubernetes, or ECS?** See the relevant page for runtime
and permission requirements:

- [nsjail on Docker](./docker.md)
- [nsjail on Kubernetes](./k8s.md)
- [nsjail on ECS](./ecs.md)

## Overview

nsjail leverages Linux namespace technology to isolate processes at the network
level. When Agent Firewall runs with nsjail, it creates a separate network
namespace for the isolated process, allowing Agent Firewall to intercept and
filter all network traffic according to the configured policy.

This jail type requires Linux capabilities to create and manage network
namespaces, which means it has specific runtime requirements when running in
containerized environments like Docker and Kubernetes.

## Architecture

<img width="1228" height="604" alt="Boundary" src="https://github.com/user-attachments/assets/1b7c8c5b-7b8f-4adf-8795-325bd28715c6" />

---

# nsjail on Docker

Source: https://coder.com/docs/ai-coder/agent-firewall/nsjail/docker

> [!NOTE]
> Agent Firewall is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

This page describes the runtime and permission requirements for running Agent
Firewall with the **nsjail** jail type on **Docker**.

For an overview of nsjail, see [nsjail](./index.md).

## Runtime & Permission Requirements for Running Boundary in Docker

This section describes the Linux capabilities and runtime configurations
required to run Agent Firewall with nsjail inside a Docker container.
Requirements vary depending on the OCI runtime and the seccomp profile in use.

### 1. Default `runc` runtime with `CAP_NET_ADMIN`

When using Docker's default `runc` runtime, Agent Firewall requires the
container to have `CAP_NET_ADMIN`. This is the minimal capability needed for
configuring virtual networking inside the container.

Docker's default seccomp profile may also block certain syscalls (such as
`clone`) required for creating unprivileged network namespaces. If you encounter
these restrictions, you may need to update or override the seccomp profile to
allow these syscalls.

[see Docker Seccomp Profile Considerations](#docker-seccomp-profile-considerations)

### 2. Default `runc` runtime with `CAP_SYS_ADMIN` (testing only)

For development or testing environments, you may grant the container
`CAP_SYS_ADMIN`, which implicitly bypasses many of the restrictions in Docker's
default seccomp profile.

- Agent Firewall does not require `CAP_SYS_ADMIN` itself.
- However, Docker's default seccomp policy commonly blocks namespace-related
  syscalls unless `CAP_SYS_ADMIN` is present.
- Granting `CAP_SYS_ADMIN` enables Agent Firewall to run without modifying the
  seccomp profile.

⚠️ Warning: `CAP_SYS_ADMIN` is extremely powerful and should not be used in
production unless absolutely necessary.

### 3. `sysbox-runc` runtime with `CAP_NET_ADMIN`

When using the `sysbox-runc` runtime (from Nestybox), Agent Firewall can run
with only:

- `CAP_NET_ADMIN`

The sysbox-runc runtime provides more complete support for unprivileged user
namespaces and nested containerization, which typically eliminates the need for
seccomp profile modifications.

## Docker Seccomp Profile Considerations

Docker's default seccomp profile frequently blocks the `clone` syscall, which is
required by Agent Firewall when creating unprivileged network namespaces. If
the `clone` syscall is denied, Agent Firewall will fail to start.

To address this, you may need to modify or override the seccomp profile used by
your container to explicitly allow the required `clone` variants.

You can find the default Docker seccomp profile for your Docker version here
(specify your docker version):

https://github.com/moby/moby/blob/v25.0.13/profiles/seccomp/default.json#L628-L635

If the profile blocks the necessary `clone` syscall arguments, you can provide a
custom seccomp profile that adds an allow rule like the following:

```json
{
    "names": ["clone"],
    "action": "SCMP_ACT_ALLOW"
}
```

This example unblocks the clone syscall entirely.

### Example: Overriding the Docker Seccomp Profile

To use a custom seccomp profile, start by downloading the default profile for
your Docker version:

https://github.com/moby/moby/blob/v25.0.13/profiles/seccomp/default.json#L628-L635

Save it locally as seccomp-v25.0.13.json, then insert the clone allow rule shown
above (or add "clone" to the list of allowed syscalls).

Once updated, you can run the container with the custom seccomp profile:

```sh
docker run -it \
  --cap-add=NET_ADMIN \
  --security-opt seccomp=seccomp-v25.0.13.json \
  test bash
```

This instructs Docker to load your modified seccomp profile while granting only
the minimal required capability (`CAP_NET_ADMIN`).

---

# nsjail on Kubernetes

Source: https://coder.com/docs/ai-coder/agent-firewall/nsjail/k8s

> [!NOTE]
> Agent Firewall is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

This page describes the runtime and permission requirements for running Agent
Firewall with the **nsjail** jail type on **Kubernetes**.

## Runtime & Permission Requirements for Running Boundary in Kubernetes

Requirements depend on the node OS and the container runtime. The following
examples use **EKS with Managed Node Groups** for two common node AMIs.

---

### Example 1: EKS + Managed Node Groups + Amazon Linux

On **Amazon Linux** nodes, the default seccomp and runtime behavior typically
allow the syscalls needed for Boundary. You only need to
grant `NET_ADMIN`.

**Container `securityContext`:**

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: coder-agent
spec:
  containers:
    - name: coder-agent
      image: your-coder-agent-image
      securityContext:
        capabilities:
          add:
            - NET_ADMIN
      # ... rest of container spec
```

---

### Example 2: EKS + Managed Node Groups + Bottlerocket

On **Bottlerocket** nodes, the default seccomp profile often blocks the `clone`
syscalls required for unprivileged user namespaces. You must either disable or
modify seccomp for the pod (see [Docker Seccomp Profile Considerations](./docker.md#docker-seccomp-profile-considerations)) or grant `SYS_ADMIN`.

**Option A: `NET_ADMIN` + disable seccomp**

Disabling the seccomp profile allows the container to create namespaces
without granting `SYS_ADMIN` capabilities.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: coder-agent
spec:
  containers:
    - name: coder-agent
      image: your-coder-agent-image
      securityContext:
        capabilities:
          add:
            - NET_ADMIN
        seccompProfile:
          type: Unconfined
      # ... rest of container spec
```

**Option B: `NET_ADMIN` + `SYS_ADMIN`**

Granting `SYS_ADMIN` bypasses many seccomp restrictions and allows namespace
creation.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: coder-agent
spec:
  containers:
    - name: coder-agent
      image: your-coder-agent-image
      securityContext:
        capabilities:
          add:
            - NET_ADMIN
            - SYS_ADMIN
      # ... rest of container spec
```

### User namespaces on Bottlerocket

User namespaces are often disabled (`user.max_user_namespaces=0`) on Bottlerocket
nodes. Check and enable user namespaces:

```sh
# Check current value
sysctl user.max_user_namespaces

# If it returns 0, enable user namespaces
sysctl -w user.max_user_namespaces=65536
```

If `sysctl -w` is not allowed, configure it via Bottlerocket bootstrap settings
when creating the node group (e.g., in Terraform):

```tf
bootstrap_extra_args = <<-EOT
  [settings.kernel.sysctl]
  "user.max_user_namespaces" = "65536"
EOT
```

This ensures Boundary can create user namespaces with nsjail.

<a id="running-without-user-namespaces"></a>

### Run without user namespaces

If the environment is restricted and you cannot enable user namespaces (e.g.
Bottlerocket in EKS auto-mode), you can run Boundary with the
`--no-user-namespace` flag. Use this when you have no way to allow user namespace creation.

---

### Example 3: EKS + Fargate (Firecracker VMs)

nsjail is not currently supported on **EKS Fargate** (Firecracker-based VMs), which
blocks the capabilities needed for nsjail.

If you run on Fargate, we recommend using [landjail](../landjail.md) instead,
provided kernel version supports it (Linux 6.7+).

---

# nsjail on ECS

Source: https://coder.com/docs/ai-coder/agent-firewall/nsjail/ecs

> [!NOTE]
> Agent Firewall is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

This page describes the runtime and permission requirements for running Agent
Firewall with the **nsjail** jail type on **Amazon ECS**.

## Runtime & Permission Requirements for Running Agent Firewall in ECS

The setup for ECS is similar to [nsjail on Kubernetes](./k8s.md); that environment
is better explored and tested, so the Kubernetes page is a useful reference. On
ECS, requirements depend on the node OS and how ECS runs your tasks. The
following examples use **ECS with Self Managed Node Groups** (EC2 launch type).

---

### Example 1: ECS + Self Managed Node Groups + Amazon Linux

On **Amazon Linux** nodes with ECS, the default Docker seccomp profile enforced
by ECS blocks the syscalls needed for Agent Firewall. Because it is difficult to
disable or modify the seccomp profile on ECS, you must grant `SYS_ADMIN` (along
with `NET_ADMIN`) so that Agent Firewall can create namespaces and run nsjail.

**Task definition (Terraform) — `linuxParameters`:**

```tf
container_definitions = jsonencode([{
  name      = "coder-agent"
  image     = "your-coder-agent-image"

  linuxParameters = {
    capabilities = {
      add = ["NET_ADMIN", "SYS_ADMIN"]
    }
  }
}])
```

This gives the container the capabilities required for nsjail when ECS uses the
default Docker seccomp profile.

---

# landjail jail type

Source: https://coder.com/docs/ai-coder/agent-firewall/landjail

> [!NOTE]
> Agent Firewall is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

landjail is Agent Firewall's alternative jail type that uses Landlock V4 for
network isolation.

## Overview

Agent Firewall uses Landlock V4 to enforce network restrictions:

- All `bind` syscalls are forbidden
- All `connect` syscalls are forbidden except to the port that is used by http
  proxy

This provides network isolation without requiring network namespace capabilities
or special Docker permissions.

---

# Rules engine documentation

Source: https://coder.com/docs/ai-coder/agent-firewall/rules-engine

> [!NOTE]
> Agent Firewall is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

## Overview

The `rulesengine` package provides a flexible rule-based filtering system for
HTTP/HTTPS requests. Rules use a simple key-value syntax with support for
wildcards and multiple values.

### Basic Syntax

Rules follow the format: `key=value [key=value ...]` with three supported keys:

- **`method`**: HTTP method(s) - Any HTTP method (e.g., `GET`, `POST`, `PUT`,
  `DELETE`), `*` (all methods), or comma-separated list
- **`domain`**: Domain/hostname pattern - `github.com`, `*.example.com`, `*`
  (all domains)
- **`path`**: URL path pattern - `/api/users`, `/api/*/users`, `*` (all paths),
  or comma-separated list

**Key behavior**:

- If a key is omitted, it matches all values
- Multiple key-value pairs in one rule are separated by whitespace
- Multiple rules in the allowlist are OR'd together (OR logic)
- Default deny: if no rule matches, the request is denied

**Examples**:

```yaml
allowlist:
  - domain=github.com # All methods, all paths for github.com (exact match)
  - domain=*.github.com # All subdomains of github.com
  - method=GET,POST domain=api.example.com # GET/POST to api.example.com (exact match)
  - domain=api.example.com path=/users,/posts # Multiple paths
  - method=GET domain=github.com path=/api/* # All three keys
```

---

## Wildcard Symbol for Domains

The `*` wildcard matches domain labels (parts separated by dots).

| Pattern        | Matches                                                     | Does NOT Match                                                           |
|----------------|-------------------------------------------------------------|--------------------------------------------------------------------------|
| `*`            | All domains                                                 | -                                                                        |
| `github.com`   | `github.com` (exact match only)                             | `api.github.com`, `v1.api.github.com` (subdomains), `github.io`          |
| `*.github.com` | `api.github.com`, `v1.api.github.com` (1+ subdomain levels) | `github.com` (base domain)                                               |
| `api.*.com`    | `api.github.com`, `api.google.com`                          | `api.v1.github.com` (`*` in the middle matches exactly one domain label) |
| `*.*.com`      | `api.example.com`, `api.v1.github.com`                      | -                                                                        |
| `api.*`        | ❌ **ERROR** - Cannot end with `*`                           | -                                                                        |

**Important**:

- Patterns without `*` match **exactly** (no automatic subdomain matching)
- `*.example.com` matches one or more subdomain levels
- To match both base domain and subdomains, use separate rules:
  `domain=github.com` and `domain=*.github.com`
- Domain patterns **cannot end with asterisk**

---

## Wildcard Symbol for Paths

The `*` wildcard matches path segments (parts separated by slashes).

| Pattern        | Matches                                                    | Does NOT Match                          |
|----------------|------------------------------------------------------------|-----------------------------------------|
| `*`            | All paths                                                  | -                                       |
| `/api/users`   | `/api/users`                                               | `/api/users/123` (subpaths don't match) |
| `/api/*`       | `/api/users`, `/api/posts`                                 | `/api`                                  |
| `/api/*/users` | `/api/v1/users`, `/api/v2/users`                           | `/api/users`, `/api/v1/v2/users`        |
| `/*/users`     | `/api/users`, `/v1/users`                                  | `/api/v1/users`                         |
| `/api/v1/*`    | `/api/v1/users`, `/api/v1/users/123/details` (1+ segments) | `/api/v1`                               |

**Important**:

- `*` matches **exactly one segment** (except at the end)
- `*` at the **end** matches **one or more segments** (special behavior)
- `*` must match an entire segment (cannot be part of a segment like
  `/api/user*`)

---

## Special Meaning of Wildcard at Beginning and End

| Position   | Domain              | Path                  |
|------------|---------------------|-----------------------|
| Beginning  | 1+ subdomain levels | Exactly 1 segment     |
| Middle     | Exactly 1 label     | Exactly 1 segment     |
| End        | ❌ Not allowed       | 1+ segments (special) |
| Standalone | All domains         | All paths             |

---

## Multipath

Specify multiple paths in a single rule by separating them with commas:

```yaml
allowlist:
  - domain=api.example.com path=/users,/posts,/comments
  - domain=api.example.com path=/api,/api/*
```

`NOTE`: The pattern `/api/*` does not include the base path `/api`. To match
both, use `path=/api,/api/*`.

---

# Version requirements

Source: https://coder.com/docs/ai-coder/agent-firewall/version

> [!NOTE]
> Agent Firewall is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

## Recommended Versions

It's recommended to use **Coder v2.30.0 or newer** and **Claude Code module
v4.7.0 or newer**.

### Coder v2.30.0+

Since Coder v2.30.0, Agent Firewall is embedded inside the Coder binary, and
you don't need to install it separately. The `coder agent-firewall` subcommand is
available directly from the Coder CLI.

### Claude Code Module v4.7.0+

Since Claude Code module v4.7.0, the embedded `coder agent-firewall` subcommand is
used by default. This means you don't need to set `boundary_version`; the
boundary version is tied to your Coder version.

## Compatibility with Older Versions

<a id="using-coder-before-v2300-with-claude-code-module-v470"></a>

### Coder before v2.30.0 with Claude Code module v4.7.0+

If you're using Coder before v2.30.0 with Claude Code module v4.7.0 or newer,
the `coder agent-firewall` subcommand isn't available in your Coder installation. In
this case, you need to:

1. Set `use_boundary_directly = true` in your Terraform module configuration
2. Explicitly set `boundary_version` to specify which Agent Firewall version
   to install

Example configuration:

```tf
module "claude-code" {
  source              = "dev.registry.coder.com/coder/claude-code/coder"
  version             = "4.7.0"
  enable_boundary     = true
  use_boundary_directly = true
  boundary_version    = "0.6.0"
}
```

<a id="using-claude-code-module-before-v470"></a>

### Claude Code module before v4.7.0

If you're using Claude Code module before v4.7.0, the module expects to use
Agent Firewall directly. You need to explicitly set `boundary_version` in your
Terraform configuration:

```tf
module "claude-code" {
  source              = "dev.registry.coder.com/coder/claude-code/coder"
  version             = "4.6.0"
  enable_boundary     = true
  boundary_version    = "0.6.0"
}
```

## Summary

| Coder Version | Claude Code Module Version | Configuration Required                                |
|---------------|----------------------------|-------------------------------------------------------|
| v2.30.0+      | v4.7.0+                    | No additional configuration needed                    |
| < v2.30.0     | v4.7.0+                    | `use_boundary_directly = true` and `boundary_version` |
| Any           | < v4.7.0                   | `boundary_version`                                    |

---

# AI Gateway

Source: https://coder.com/docs/ai-coder/ai-gateway

![AI Gateway diagram](../../images/aibridge/aibridge_diagram.png)

AI Gateway is a smart gateway for AI. It acts as an intermediary between your users' coding agents / IDEs
and providers like OpenAI and Anthropic. By intercepting all the AI traffic between these clients and
the upstream APIs, AI Gateway can record user prompts, token usage, and tool invocations.
AI Gateway supports clients running inside or outside Coder workspaces.
You can run the gateway inside the Coder control plane (`coderd`) or as a [standalone service](./standalone.md).

AI Gateway solves 3 key problems:

1. **Centralized authn/z management**: no more issuing & managing API tokens for OpenAI/Anthropic usage.
   Users use their Coder session or API tokens to authenticate with `coderd`, and
   `coderd` securely communicates with the upstream APIs on their behalf.
1. **Auditing and attribution**: all interactions with AI services, whether autonomous or human-initiated,
   are audited and attributed back to a user.
1. **Centralized MCP administration**: define a set of approved MCP servers and tools which your users may
   use.

> [!NOTE]
> AI Gateway is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.
>
> AI Gateway was previously known as "AI Bridge". Visit [Rebranding Migration](./rebranding-migration.md) for details.

## When to use AI Gateway

As LLM adoption grows, administrators need centralized auditing, monitoring, and token management. AI Gateway enables organizations to manage AI tooling access for thousands of engineers from a single control plane.

If you are an administrator or devops leader looking to:

- Measure AI tooling adoption across teams or projects
- Establish an audit trail of prompts, issues, and tools invoked
- Manage token spend in a central dashboard
- Investigate opportunities for AI automation
- Uncover high-leverage use cases last

AI Gateway is best suited for organizations facing these centralized management and observability challenges.

## Next steps

- [Set up AI Gateway](./setup.md) on your Coder deployment
- Optionally, [deploy AI Gateway as a standalone service](./standalone.md)
- [Configure AI clients](./clients/index.md) to use AI Gateway
- [Configure MCP servers](./mcp.md) for tool access
- [Audit AI sessions](./audit.md)
- [Monitor usage and metrics](./monitoring.md) and [configure data retention](./setup.md#data-retention)
- [Reference documentation](./reference.md)

<children></children>

---

# Setup

Source: https://coder.com/docs/ai-coder/ai-gateway/setup

By default, AI Gateway runs inside the Coder control plane (`coderd`) and requires no separate compute.
In embedded mode, `coderd` runs the gateway in memory and brokers traffic to your configured AI providers on behalf of authenticated users.

If AI traffic needs dedicated compute, independent scaling, or a separate network endpoint, you can [deploy AI Gateway as a standalone service](./standalone.md).

Provider records are managed through the dashboard or API and stored in the database.
Provider environment variables, flags, and YAML options no longer seed the database.
Refer to [Database management of providers](./providers.md#database-management-of-providers) for details.

## Activation

The AI Gateway feature must be enabled in the Coder deployment configuration before
embedded or standalone gateway instances can serve authenticated traffic.

_AI Gateway is enabled by default as of v2.34._

```sh
export CODER_AI_GATEWAY_ENABLED=true
coder server
# or
coder server --ai-gateway-enabled=true
```

A standalone process does not read `CODER_AI_GATEWAY_ENABLED` from its own environment.
However, this setting must remain enabled on `coderd`.
It is required for gateway key management endpoints to work and for standalone replicas to connect to the control plane.

## Configure Providers

Configure at least one provider before exposing AI Gateway to end users.

Providers are deployment-scoped. Add them from the dashboard or the
[AI Providers API](../../reference/api/aiproviders.md). Changes take effect
without restarting `coderd`.

### Dashboard

1. Navigate to **Admin settings** > **AI**
1. Select **Providers**
1. Select **Add provider**
1. Select the provider type
1. Enter a unique lowercase name, the upstream endpoint, and the credentials
1. Save the provider

Each provider gets its own AI Gateway route at
`/api/v2/ai-gateway/<provider-name>/`.

> [!NOTE]
> Provider names must be unique and use lowercase, hyphen-separated identifiers
> such as `anthropic-corp` or `azure-openai`. Once deleted, another provider
> may reuse the name.

![AI Providers list page](../../images/aibridge/providers-list.png)

![Add Anthropic provider form](../../images/aibridge/provider-add-anthropic.png)

Open an existing provider to rotate credentials, update its endpoint, or
disable it without restarting `coderd`.

![Edit Anthropic provider form](../../images/aibridge/provider-edit-anthropic.png)

## API Dumps

AI Gateway can dump provider request and response pairs to disk for debugging.
Configure the dump directory with `--ai-gateway-dump-dir` or
`CODER_AI_GATEWAY_DUMP_DIR`:

```sh
coder server --ai-gateway-dump-dir=/var/lib/coder/ai-gateway-dumps
```

Or in YAML:

```yaml
ai_gateway:
  api_dump_dir: /var/lib/coder/ai-gateway-dumps
```

This top-level setting replaces the previous per-provider `DUMP_DIR` field.
For each provider, AI Gateway writes dumps under `<base>/<provider_name>`, where
`<base>` is the configured dump directory and `<provider_name>` is the provider
instance name used in the route. For example, a provider named `anthropic-corp`
with `/var/lib/coder/ai-gateway-dumps` configured writes to
`/var/lib/coder/ai-gateway-dumps/anthropic-corp`.

Sensitive headers are redacted before dumps are written. Leave the value empty
to disable dumping.

Each [standalone gateway](./standalone.md) replica accepts the same API dump settings and writes optional dumps to its own local disk.

> [!WARNING]
> API dumps are intended for short diagnostic sessions only. Dump files contain
> raw request and response data, which may include proprietary or sensitive
> information such as prompts, completions, and tool inputs. Protect the target
> directory and disable dumping when diagnostics are complete.

## Send actor headers

Enable `send_actor_headers` to add authenticated actor identity to intercepted upstream requests.
The setting is disabled by default.

```sh
CODER_AI_GATEWAY_SEND_ACTOR_HEADERS=true
```

You can also enable the setting with `--ai-gateway-send-actor-headers` or `ai_gateway.send_actor_headers`.
Configure the ID, username, and email header names independently with `CODER_AI_GATEWAY_ACTOR_HEADER_ID`, `CODER_AI_GATEWAY_ACTOR_HEADER_USERNAME`, and `CODER_AI_GATEWAY_ACTOR_HEADER_EMAIL`:

```yaml
ai_gateway:
  send_actor_headers: true
  actor_header_id: X-AI-Bridge-Actor-ID
  actor_header_username: X-AI-Bridge-Actor-Metadata-Username
  actor_header_email: ""
```

The equivalent CLI options are `--ai-gateway-actor-header-id`, `--ai-gateway-actor-header-username`, and `--ai-gateway-actor-header-email`.
The email header is empty by default.
To forward email, set `actor_header_email`, for example to `X-AI-Bridge-Actor-Metadata-Email`.
The setting applies to every configured provider, so enable it only if all of them, and any proxy in between, may receive user email addresses.
For defaults, precedence, and privacy considerations, refer to [Actor header forwarding](./reference.md#actor-header-forwarding).

## Data Retention

AI Gateway records prompts, token usage, tool invocations, and model reasoning for auditing and
monitoring purposes. By default, this data is retained for **60 days**.

Configure retention using `--ai-gateway-retention` or `CODER_AI_GATEWAY_RETENTION`:

```sh
coder server --ai-gateway-retention=90d
```

Or in YAML:

```yaml
ai_gateway:
  retention: 90d
```

Set to `0` to retain data indefinitely.

For duration formats, how retention works, and best practices, see the
[Data Retention](../../admin/setup/data-retention.md) documentation.

## Structured Logging

AI Gateway can emit structured logs for every interception record, making it
straightforward to export data to external SIEM or observability platforms.

Enable with `--ai-gateway-structured-logging` or `CODER_AI_GATEWAY_STRUCTURED_LOGGING`:

```sh
coder server --ai-gateway-structured-logging=true
```

Or in YAML:

```yaml
ai_gateway:
  structured_logging: true
```

These logs are written to the same output stream as all other `coderd` logs,
using the format configured by
[`--log-human`](../../reference/cli/server/index.md#--log-human) (default, writes to
stderr) or [`--log-json`](../../reference/cli/server/index.md#--log-json). For machine
ingestion, set `--log-json` to a file path or `/dev/stderr` so that records are
emitted as JSON.

### Choose which process emits the records

By default `coderd` emits these records as they arrive from the gateway.
Set `--ai-gateway-structured-logging-source` to change that:

| Value     | Emitted by             | Use it when                                                                                   |
|-----------|------------------------|-----------------------------------------------------------------------------------------------|
| `coderd`  | `coderd` (default)     | You want today's behavior.                                                                    |
| `gateway` | The AI Gateway process | You need records that the gateway never persists, such as when content recording is disabled. |
| `both`    | Both processes         | You are moving from one to the other and want to compare the two streams.                     |

```sh
coder server --ai-gateway-structured-logging=true \
  --ai-gateway-structured-logging-source=gateway
```

Gateway-emitted records carry the same message, the same `record_type` values and the same fields, with one exception: they omit `thread_parent_id` and `thread_root_id`.
Those are resolved from recorded tool usage by a database lookup that only `coderd` can perform.

> [!IMPORTANT]
> With `both`, every record that reaches `coderd` is logged twice.
> Deduplicate on `interception_id`, `record_type` and `msg_id` if your pipeline counts records.

When the gateway emits the records, they are written to the gateway's log output rather than `coderd`'s, and under a different logger name.
Match on the `"interception log"` message rather than the logger name so that your pipeline works with either source.

On a [standalone gateway](./standalone.md), set `CODER_AI_GATEWAY_STRUCTURED_LOGGING` and `CODER_AI_GATEWAY_STRUCTURED_LOGGING_SOURCE` on **both** processes, and ship the gateway's logs.

## Disable content recording

Three of the record types store conversation content verbatim: `aibridge_user_prompts.prompt`, `aibridge_tool_usages.input` and `aibridge_model_thoughts.content`.
Deployments that want AI Governance cost controls without retaining conversation content can stop recording them:

```sh
coder server --ai-gateway-disable-content-recording=true
```

Or in YAML:

```yaml
ai_gateway:
  disable_content_recording: true
```

Interceptions and token usage are still recorded, so [cost controls](./cost-controls.md) are unaffected.

This option only stops the records being written to the database.
To keep exporting them to your SIEM, combine it with gateway-emitted structured logs:

```sh
coder server --ai-gateway-disable-content-recording=true \
  --ai-gateway-structured-logging=true \
  --ai-gateway-structured-logging-source=gateway
```

Without `--ai-gateway-structured-logging-source=gateway`, the dropped records reach neither the database nor your SIEM, because `coderd` never receives them.
The gateway logs a warning at startup in that configuration.

### What you lose

Disabling content recording is a governance trade-off, not only a storage saving:

- **Session grouping degrades** for clients that don't send their own session ID.
  Coder groups those interceptions into threads by correlating recorded tool calls, so without tool usage records each interception becomes its own session.
  The grouping is stored when the row is written, so it can't be recovered later by re-enabling the option.
- **Sessions pages are largely empty**, since there is no prompt, tool call or reasoning content to show.
- **Prompt and tool call telemetry report zero**.
- **The audit trail of what was asked is gone**, including for incident review.

Token counts, spend, model and provider attribution, and request volume are all unaffected, as are the [Prometheus metrics](./monitoring.md) for prompt and tool call counts.

Filter for AI Gateway records in your logging pipeline by matching on the
`"interception log"` message. Each log line includes a `record_type` field that
indicates the kind of event captured:

| `record_type`        | Description                             | Key fields                                                                     |
|----------------------|-----------------------------------------|--------------------------------------------------------------------------------|
| `interception_start` | A new intercepted request begins.       | `interception_id`, `initiator_id`, `provider`, `model`, `client`, `started_at` |
| `interception_end`   | An intercepted request completes.       | `interception_id`, `ended_at`                                                  |
| `token_usage`        | Token consumption for a response.       | `interception_id`, `input_tokens`, `output_tokens`, `created_at`               |
| `prompt_usage`       | The last user prompt in a request.      | `interception_id`, `prompt`, `created_at`                                      |
| `tool_usage`         | A tool/function call made by the model. | `interception_id`, `tool`, `input`, `server_url`, `injected`, `created_at`     |
| `model_thought`      | Model reasoning or thinking content.    | `interception_id`, `content`, `created_at`                                     |

---

# Deploy AI Gateway as a standalone service

Source: https://coder.com/docs/ai-coder/ai-gateway/standalone

> [!NOTE]
> AI Gateway requires a [Premium](../ai-governance.md) license.
> Community deployments cannot access AI Gateway.

When AI traffic needs dedicated compute, independent scaling, or a separate network endpoint, you can deploy AI Gateway separately from the Coder control plane (`coderd`).

A standalone AI gateway serves client traffic on its own listener and maintains a control connection to `coderd`.
`coderd` continues to manage authentication, authorization, provider configuration, and AI session records.

## Before you begin

A standalone AI gateway requires the following:

- Coder v2.36.0 or later.
- A [Premium license with AI Governance](../ai-governance.md).
- AI Gateway enabled on the Coder control plane with `CODER_AI_GATEWAY_ENABLED=true` or `--ai-gateway-enabled=true`.
- The full Coder image or a Coder binary that includes the `coder ai-gateway start` command.

`coder ai-gateway start` does not read `CODER_AI_GATEWAY_ENABLED` from the standalone process.
However, this setting must remain enabled on `coderd` for gateway key management and standalone control connections.

## Create a gateway key

Each standalone replica uses a gateway key to authenticate and establish its control connection to `coderd`.
Gateway key management requires site-level `ai_gateway_key` permissions, which only the built-in **owner** role includes.
Coder custom roles are organization-scoped and cannot grant site-level permissions.

Log in to the Coder CLI as an **owner**, then create a dedicated key for the standalone deployment:

```sh
coder login https://coder.example.com
coder ai-gateway keys create standalone-production
```

Save the key from the command output immediately because Coder does not display the plaintext value again.

A single key can authenticate multiple replicas in the same deployment.
For independent rotation and revocation, use a separate key for each standalone deployment or environment.

## Start a standalone process

Set the Coder URL, gateway key, and listener address, then start the gateway:

```sh
export CODER_URL=https://coder.example.com
export CODER_AI_GATEWAY_KEY='<gateway_key>'
export CODER_AI_GATEWAY_HTTP_ADDRESS=0.0.0.0:4001
coder ai-gateway start
```

Use `CODER_AI_GATEWAY_KEY_FILE` instead of `CODER_AI_GATEWAY_KEY` to read the key from a file.
The standalone process does not require a user login or `CODER_SESSION_TOKEN` after you provide the gateway key.

The listener defaults to `127.0.0.1:4001`, which accepts connections only from the local host.
Set `CODER_AI_GATEWAY_HTTP_ADDRESS` to a routable address, as shown previously, before other hosts or pods can reach the gateway.

The standalone gateway fetches provider configuration from `coderd`.
Configure at least one [AI provider](./providers.md) in Coder before sending provider traffic through the gateway.

The listener uses HTTP by default.
Set both `CODER_AI_GATEWAY_TLS_CERT_FILE` and `CODER_AI_GATEWAY_TLS_KEY_FILE` to terminate TLS in the process.
For all command options, refer to [`coder ai-gateway start`](../../reference/cli/ai-gateway/start.md).

## Run AI Gateway in Kubernetes

To run the standalone gateway as a Kubernetes workload, provide the same environment variables and network access to the Coder URL.
You can manage the workload with your own Kubernetes manifests or use the provided Helm chart.
The chart configures the Deployment, probes, and Service, plus an optional Ingress or `HTTPRoute`.

To use the Kubernetes examples, install `kubectl` and configure access to the cluster where AI Gateway will run.
Install Helm if you use the chart.

Create a namespace and store the gateway key in a Kubernetes Secret:

```sh
kubectl create namespace coder-ai-gateway
kubectl create secret generic coder-ai-gateway-key \
  --namespace coder-ai-gateway \
  --from-literal=key='<gateway_key>'
```

### Configure the Helm chart

Create `ai-gateway-values.yaml` with at least the Coder URL and key Secret:

```yaml
coder:
  env:
    - name: CODER_URL
      value: https://coder.example.com

aigateway:
  keySecret:
    name: coder-ai-gateway-key
```

The gateway must be able to reach the Coder URL from every replica.
For an HTTPS URL signed by a private CA, set `aigateway.coderTLS.caSecret.name` to the Secret holding the CA bundle.
If Coder requires client mTLS, also set `aigateway.coderTLS.clientSecret.name`.

The chart defaults to one replica, a `ClusterIP` Service, and a data-plane listener on port 4001.
It also enables a separate Prometheus listener on port 2112.
Ingress and `HTTPRoute` are disabled by default.

For the complete chart configuration, including private CAs, mTLS, Ingress, Kubernetes Gateway API, and additional manifests, refer to the [AI Gateway Helm chart README](../../../helm/ai-gateway/README.md).

### Install the Helm chart

Install the chart version that matches the Coder control plane from GitHub Container Registry:

```sh
helm install ai-gateway \
  oci://ghcr.io/coder/chart/coder-ai-gateway \
  --namespace coder-ai-gateway \
  --values ai-gateway-values.yaml \
  --version '<chart version>'
```

Chart versions omit the leading `v`, so use `2.36.0` rather than `v2.36.0`.

When you install the chart directly from a Git checkout, set `coder.image.tag` explicitly and install `./helm/ai-gateway`.
Released chart packages select the matching Coder image by default.
If you need to run different `coderd` and gateway versions, refer to [Version compatibility](#version-compatibility).

### Validate the Helm deployment

Wait for the Deployment to become available:

```sh
kubectl rollout status deployment/coder-ai-gateway \
  --namespace coder-ai-gateway \
  --timeout=5m
```

The chart configures the following probes by default:

- The liveness probe requests `/healthz` and verifies that the HTTP listener is serving.
- The readiness probe requests `/readyz` and verifies that the gateway is connected to `coderd` and has completed its initial provider load.
- The startup probe is disabled by default.

`/healthz` can return HTTP 200 while `/readyz` returns HTTP 503.
This occurs while the initial connection to `coderd` is being established, before the initial provider load, and whenever the control connection drops.
A replica can only become ready after its initial provider load succeeds, and it returns to ready whenever the control connection recovers.
Kubernetes removes an unready replica from the Service, so clients normally stop reaching it.
A request that still arrives waits for the control connection instead of failing.

Port-forward the Service to inspect both endpoints:

```sh
kubectl port-forward \
  --namespace coder-ai-gateway \
  service/coder-ai-gateway \
  4001:80
```

In another terminal, run:

```sh
curl --fail http://127.0.0.1:4001/healthz
curl --fail http://127.0.0.1:4001/readyz
```

Both endpoints return HTTP 200 with an empty body when the replica is serving and ready.

List gateway keys and verify that the key has a recent heartbeat:

```sh
coder ai-gateway keys list
```

The `LAST HEARTBEAT AT` column holds the timestamp.
The first heartbeat is recorded when the replica connects.
An active control connection updates the timestamp every 60&nbsp;seconds.
Coder stores one timestamp per key, so a recent heartbeat on a shared key does not confirm that every replica is connected.
Check `/readyz` on each replica to verify individual health.

## Route traffic to the standalone gateway

The standalone deployment does not move traffic automatically.
Configure AI Gateway Proxy and direct AI clients to send requests to the standalone endpoint.

### AI Gateway Proxy

[AI Gateway Proxy](./ai-gateway-proxy/index.md) remains part of the `coderd` process.
Configure its target to use the standalone Service, Ingress, `HTTPRoute`, or load balancer.

If you installed the Helm chart, get the exact in-cluster Service URL from the chart notes:

```sh
helm get notes ai-gateway --namespace coder-ai-gateway
```

If you use your own Kubernetes manifests, use the URL of the Service you created.
Set the Service URL on the Coder control plane, for example:

```sh
CODER_AI_GATEWAY_PROXY_TARGET=http://coder-ai-gateway.coder-ai-gateway.svc.cluster.local:80
```

Restart or upgrade the Coder deployment after changing this setting.
The proxy appends the provider name and request path to the target, so do not include query parameters.

### Direct AI clients

Clients that use `<Coder access URL>/api/v2/ai-gateway/<provider-name>/` continue to reach the embedded gateway.
To route these clients to the standalone gateway, replace the Coder access URL and the embedded `/api/v2/ai-gateway` path prefix with the standalone endpoint while keeping the provider path.

For example, if the gateway is reachable at `https://ai-gateway.example.com` and the providers are configured, configure Claude Code with the following:

```sh
ANTHROPIC_BASE_URL=https://ai-gateway.example.com/anthropic
```

Configure an OpenAI-compatible client with the following:

```sh
OPENAI_BASE_URL=https://ai-gateway.example.com/openai/v1
```

For full per-client configuration examples, refer to [Client Configuration](./clients/index.md).

### Expose the standalone AI gateway

If clients cannot access the in-cluster Service, expose the gateway through an Ingress, an `HTTPRoute`, or a load balancer Service.
In the provided Helm chart, set the following:

```yaml
service:
  type: LoadBalancer
```

Use TLS to protect credentials and AI traffic whenever they cross an untrusted network.
Prefer TLS termination at the Ingress or Kubernetes Gateway when your platform already manages certificates there.
To terminate TLS in the gateway process, set `aigateway.listenerTLS.name` to an existing TLS Secret.

If `CODER_AI_GATEWAY_PROXY_TARGET` uses HTTPS with a private CA, add that CA to the trust store of the `coderd` pods before changing the proxy target.
For the Coder Helm chart, you can mount a CA bundle with `coder.certs.secrets`.
This trust configuration is separate from `aigateway.coderTLS.caSecret`, which configures the connection from the standalone gateway to `coderd`.

## Scale replicas

Run multiple replicas behind a Service or load balancer.
In the provided Helm chart, set the following:

```yaml
coder:
  replicaCount: 3
```

The Service balances requests across ready replicas.
Each replica maintains its own control connection, local caches, concurrency limits, request metrics, logs, and traces.
All replicas fetch provider configuration from the same Coder deployment and write AI session records through `coderd`.
Cost control metrics are registered only on `coderd`, so `coder_ai_gateway_cost_control_*` series never appear on a replica's Prometheus listener.
Budget enforcement also runs in `coderd` over the control connection rather than per replica.
Sticky load balancing can improve cache efficiency, but it is not required for correctness.

When you enable [API dumps](./setup.md#api-dumps), each replica writes dumps to its own local disk.
Use persistent storage if you need those files to survive pod replacement.

The chart requests 1&nbsp;CPU and 1&nbsp;GiB of memory per replica and does not set resource limits.
Measure production traffic before changing requests, limits, or `CODER_AI_GATEWAY_MAX_CONCURRENCY`.
The chart does not create a Horizontal Pod Autoscaler or PodDisruptionBudget.

## Migrate from the embedded gateway

Use a gradual cutover so that you can validate the standalone data plane before moving production traffic:

1. Upgrade `coderd` to the target Coder version.
1. Keep `CODER_AI_GATEWAY_ENABLED=true` on `coderd`.
1. Create a dedicated gateway key.
1. Deploy one standalone replica without changing client or proxy routing.
1. Verify `/readyz`, the key heartbeat, metrics, logs, and traces.
1. Send a test request directly to the standalone gateway and confirm that the AI session appears in Coder.
1. Set `CODER_AI_GATEWAY_PROXY_TARGET` to the standalone endpoint.
1. Update direct client base URLs that should use the standalone endpoint.
1. Scale the standalone deployment after the canary path is stable.

Keep `CODER_AI_GATEWAY_ENABLED=true` on `coderd` after the cutover.
The setting is required for standalone control connections and Coder features that use the in-process gateway.

## Roll back to the embedded gateway

To return traffic to the embedded gateway:

1. Remove `CODER_AI_GATEWAY_PROXY_TARGET`, or set it to `<Coder access URL>/api/v2/ai-gateway`.
1. Restart or upgrade `coderd` so the proxy target change takes effect.
1. Restore direct client base URLs to `<Coder access URL>/api/v2/ai-gateway/<provider-name>/`.
1. Verify requests and AI session records through the embedded route.
1. Scale down or uninstall the standalone deployment.
1. Delete the standalone gateway key after all replicas have stopped.

Delete the key with the following command:

```sh
coder ai-gateway keys delete standalone-production
```

Deleting a key prevents new connections immediately.
An established connection closes when its next heartbeat detects the deletion, within 60&nbsp;seconds.
The replica then tries to reconnect, receives HTTP 401, and treats that as fatal: the process exits non-zero rather than retrying.
Stop the deployment before deleting its key.

## Version compatibility

The standalone gateway image does not need to match the `coderd` image version exactly.
The components can connect when their AI Gateway API versions are compatible, and `coderd` checks AI Gateway API compatibility whenever a gateway replica connects.

A replica may use the same AI Gateway API version as `coderd` or an earlier minor version of the same major version, but never a newer one.
The gateway treats certain handshake failures from `/api/v2/ai-gateway/serve` as fatal and exits rather than retrying:

- HTTP 400: incompatible API version.
- HTTP 401: invalid gateway key.
- HTTP 403: missing entitlement.
- HTTP 404: endpoint not found.
  `coderd` may be too old and not expose the `/serve` endpoint.

Sequence changes that move both components:

- To upgrade, upgrade `coderd` first, then roll out the standalone gateway release.
- To roll back, roll back the standalone gateway first, then roll back `coderd`.

Running the same Coder release on `coderd` and every standalone replica is the simplest way to stay compatible, but it is not required.

---

# Authentication

Source: https://coder.com/docs/ai-coder/ai-gateway/auth

> [!NOTE]
> AI Gateway is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

AI Gateway uses different credentials for different kinds of connections:

- AI clients use a Coder API token to authenticate with AI Gateway as a user.
- Standalone gateway replicas use AI Gateway keys to connect to the Coder control plane.
- AI Gateway uses provider credentials configured by an administrator to authenticate to upstream AI providers.
- In [Bring Your Own Key (BYOK)](#bring-your-own-key-byok) mode, a user also supplies a personal provider credential or subscription token.

These credentials are not interchangeable.
A gateway key does not authenticate an AI client, and a Coder API token does not authenticate a standalone replica.

## Authenticate AI clients

AI Gateway authenticates clients with the same Coder API token that a user uses for the rest of the Coder API.
No separate AI Gateway login is required for client traffic.
For token creation, expiration, and revocation, refer to [Sessions and API tokens](../../admin/users/sessions-tokens.md).

Authenticating with a Coder token avoids distributing centralized provider API keys, such as OpenAI or Anthropic keys, to individual users.
AI Gateway handles upstream credentials centrally and forwards each request to the configured provider on the user's behalf.

The exact environment variable or setting name differs between tools.
Refer to the list of [supported clients](./clients/index.md) and your tool's documentation for details.

### Create a Coder API token

You can generate a token from the Coder dashboard or the CLI.

From the dashboard, go to **Account settings** > **Tokens** and create a new token.
For long-lived tokens, refer to [Sessions and API tokens](../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself).
For headless or service-account use, refer to [Headless authentication](../../admin/users/headless-auth.md).

From the CLI, print your current session token with [`coder login token`](../../reference/cli/login/token.md):

```sh
coder login token
```

Or create a new long-lived token with a name and lifetime:

```sh
coder tokens create --lifetime 30d -n my-ai-token
```

Use short lifetimes for automation and CI to limit the blast radius if a token leaks.

### Retrieve your session token

If you're logged in with the Coder CLI, retrieve your current session token with [`coder login token`](../../reference/cli/login/token.md):

```sh
export ANTHROPIC_API_KEY=$(coder login token)
export ANTHROPIC_BASE_URL="https://coder.example.com/api/v2/ai-gateway/anthropic"
```

### AI Gateway Proxy authentication

For tools that don't support a configurable base URL,
[AI Gateway Proxy](./ai-gateway-proxy/index.md) intercepts traffic and forwards it to AI Gateway.
The Coder token is supplied in the proxy URL:

```sh
export HTTPS_PROXY="https://coder:$(coder login token)@<proxy-host>:8888"
```

The client machine also needs to trust the proxy's CA certificate.
For full setup, refer to [AI Gateway Proxy setup](./ai-gateway-proxy/setup.md).

## Authenticate standalone gateway replicas

AI Gateway keys are scoped to the Coder deployment.
A [standalone AI gateway](./standalone.md) uses one of these keys to connect to `coderd`.
Only the built-in **owner** role can create, list, and delete these keys.
Coder custom roles are organization-scoped and cannot grant the site-level `ai_gateway_key` permissions.

Create a key with a descriptive name:

```sh
coder ai-gateway keys create standalone-production
```

The command displays the plaintext key once.
Save it immediately in your secret manager, because you cannot retrieve it later.
Coder stores only a short prefix of the key for display and a SHA-256 hash for authentication, never the full secret.

Names must be unique, 64 characters or fewer, and use only lowercase letters, numbers, and hyphens.
A name cannot start or end with a hyphen or contain consecutive hyphens.
Gateway keys do not expire and cannot be scoped or restricted.

Configure the standalone process with either of the following options, but not both:

- `CODER_AI_GATEWAY_KEY` or `--key` supplies the key directly.
- `CODER_AI_GATEWAY_KEY_FILE` or `--key-file` reads the key from a file.

A user login and `CODER_SESSION_TOKEN` are not used by `coder ai-gateway start`.
The same gateway key can authenticate multiple replicas.
Separate keys make it easier to rotate or revoke each deployment independently.

List keys and the most recent heartbeat for each:

```sh
coder ai-gateway keys list
```

A replica records a heartbeat when its control connection is established, then refreshes it every 60&nbsp;seconds while that connection is active.
The heartbeat reports control-connection liveness rather than client request volume.
Coder stores one timestamp per key, so replicas that share a key cannot be distinguished.

For usage and flags, refer to the generated CLI reference for [creating](../../reference/cli/ai-gateway/keys/create.md), [listing](../../reference/cli/ai-gateway/keys/list.md), and [deleting](../../reference/cli/ai-gateway/keys/delete.md) gateway keys.

### Rotate a gateway key

Rotate a key with a rolling restart.
Run more than 1 replica behind a load balancer so client traffic continues during the rollout:

1. Create a new gateway key.
1. Update the Kubernetes Secret, environment variable, or key file used by every replica.
1. Restart or roll out the standalone deployment so every replica uses the new key.
1. Verify readiness and confirm that the new key has a recent heartbeat.
1. Delete the old key.

Delete a key by name or ID:

```sh
coder ai-gateway keys delete standalone-production
```

Add `--yes` to skip the confirmation prompt in automation.

Deleting a key rejects new connections immediately.
An established session closes when its next heartbeat detects the deletion, within 60&nbsp;seconds.
The replica then tries to reconnect, receives HTTP 401, and treats that as fatal: the process exits non-zero rather than retrying.
Stop or update every replica before deleting its key for an orderly rotation.

## Authenticate to upstream providers

Administrators configure provider credentials in the Coder dashboard or with the [AI Providers API](../../reference/api/aiproviders.md).
Standalone replicas fetch this provider configuration from `coderd`, so do not copy centralized provider credentials into each standalone deployment.

For provider setup and credential failover, refer to [Provider configuration](./providers.md).

## Bring Your Own Key (BYOK)

In addition to centralized key management, AI Gateway supports Bring Your Own Key (BYOK) mode.
Users can provide their own LLM API keys or provider subscriptions,
such as Claude Pro or Max and ChatGPT Plus or Pro,
while AI Gateway continues to provide observability and governance.

![BYOK authentication flow](../../images/aibridge/clients/byok_auth_flow.png)

In BYOK mode, users need two credentials:

- A Coder API token to authenticate with AI Gateway.
- Their own LLM credential, such as a personal API key or subscription token, which AI Gateway forwards to the upstream provider.

BYOK and centralized modes can be used together.
When a user provides their own credential, AI Gateway forwards it directly.
When no user credential is present, AI Gateway uses the administrator-configured provider key.
This approach offers centralized keys as a default
while allowing individual users to bring their own key.

> [!NOTE]
> When a BYOK credential is present, [key failover](./providers.md#key-failover)
> is skipped.

Coder Agents requests routed through AI Gateway are in-process control plane requests, not external client requests that send their own AI Gateway bearer token.
Coder Agents use the same global BYOK setting.
When BYOK is enabled, users can save personal API keys for any enabled AI provider from the Agents settings page. For AWS Bedrock providers, the personal key is an AWS Bedrock API key that AI Gateway forwards as a bearer token in place of the deployment-managed AWS credentials, for every model family Bedrock serves.
Refer to [Agents credential selection](../agents/models.md#credential-selection) for the Agents-specific behavior.

Visit individual [client pages](./clients/index.md) for configuration details.

### Enable or disable BYOK

BYOK is enabled by default.
Administrators can disable it for the embedded gateway with `--ai-gateway-allow-byok=false` or `CODER_AI_GATEWAY_ALLOW_BYOK=false`:

```sh
coder server --ai-gateway-allow-byok=false
```

For a standalone gateway, set the option on each replica:

```sh
CODER_AI_GATEWAY_ALLOW_BYOK=false coder ai-gateway start
```

Each replica enforces its own local value, which governs only the traffic that replica handles.
The standalone process does not receive the `coderd` value, so set the option on every replica that should reject BYOK requests.
When disabled, BYOK requests are rejected with a `403 Forbidden` response, and only centralized provider credentials are permitted.

---

# Client Configuration

Source: https://coder.com/docs/ai-coder/ai-gateway/clients

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

Once AI Gateway is setup on your deployment, the AI coding tools used by your users will need to be configured to route requests via AI Gateway.

There are two ways to connect AI tools to AI Gateway:

- Base URL configuration (Recommended): Most AI tools allow customizing the base URL for API requests. This is the preferred approach when supported.
- AI Gateway Proxy: For tools that don't support base URL configuration, [AI Gateway Proxy](../ai-gateway-proxy/index.md) can intercept traffic and forward it to AI Gateway.

> [!NOTE]
> AI Gateway works with tools running inside or outside of Coder workspaces.
> For non-workspace setup, visit [External and Desktop Clients](#external-and-desktop-clients).

## Base URLs

Most AI coding tools allow the "base URL" to be customized. In other words, when a request is made to OpenAI's API from your coding tool, the API endpoint such as [`/v1/chat/completions`](https://platform.openai.com/docs/api-reference/chat) will be appended to the configured base. Therefore, instead of the default base URL of `https://api.openai.com/v1`, you'll need to set it to `https://coder.example.com/api/v2/ai-gateway/openai/v1`.

The exact configuration method varies by client, some use environment variables, others use configuration files or UI settings:

- **OpenAI-compatible clients**: Set the base URL (commonly via the `OPENAI_BASE_URL` environment variable) to `https://coder.example.com/api/v2/ai-gateway/openai/v1`
- **Anthropic-compatible clients**: Set the base URL (commonly via the `ANTHROPIC_BASE_URL` environment variable) to `https://coder.example.com/api/v2/ai-gateway/anthropic`

Replace `coder.example.com` with your actual Coder deployment URL.

If you run a [standalone AI gateway](../standalone.md), point clients at the gateway endpoint and drop the `/api/v2/ai-gateway` path prefix (for example, `https://ai-gateway.example.com/openai/v1` or `https://ai-gateway.example.com/anthropic`).

## Authentication

For information about authenticating with AI Gateway, visit [AI Gateway Authentication](../auth.md).

## Compatibility

The table below shows tested AI clients and their compatibility with AI Gateway.

| Client                            | OpenAI | Anthropic | BYOK | Notes                                                                                                                                                  |
|-----------------------------------|--------|-----------|------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| [Xum](./xum.md)                   | ✅      | ✅         | -    |                                                                                                                                                        |
| [Claude Code](./claude-code.md)   | -      | ✅         | ✅    |                                                                                                                                                        |
| [Codex CLI](./codex.md)           | ✅      | -         | ✅    |                                                                                                                                                        |
| [OpenCode](./opencode.md)         | ✅      | ✅         | ✅    |                                                                                                                                                        |
| [Factory](./factory.md)           | ✅      | ✅         | ✅    |                                                                                                                                                        |
| [Cline](./cline.md)               | ✅      | ✅         | ✅    |                                                                                                                                                        |
| [Kilo Code](./kilo-code.md)       | ✅      | ✅         | ❌    |                                                                                                                                                        |
| [VS Code](./vscode.md)            | ✅      | ✅         | ❌    | VS Code 1.122+ via Custom Endpoint provider. GitHub sign-in not required. Inline suggestions still require GitHub Copilot.                             |
| [JetBrains IDEs](./jetbrains.md)  | ✅      | ❌         | ❌    | Works in Chat mode via [third-party model configuration](https://www.jetbrains.com/help/ai-assistant/use-custom-models.html#provide-your-own-api-key). |
| [Junie](./junie.md)               | ✅      | ✅         | ✅    | Junie CLI via custom model profiles.                                                                                                                   |
| [Zed](./zed.md)                   | ✅      | ✅         | ❌    |                                                                                                                                                        |
| [GitHub Copilot](./copilot.md)    | ⚙️     | -         | -    | Requires [AI Gateway Proxy](../ai-gateway-proxy/index.md). Uses per-user GitHub tokens.                                                                |
| Devin Desktop (formerly Windsurf) | ❌      | ❌         | ❌    | No option to override base URL.                                                                                                                        |
| Cursor                            | ❌      | ❌         | ❌    | Override for OpenAI broken ([upstream issue](https://forum.cursor.com/t/requests-are-sent-to-incorrect-endpoint-when-using-base-url-override/144894)). |
| Sourcegraph Amp                   | ❌      | ❌         | ❌    | No option to override base URL.                                                                                                                        |
| Kiro                              | ❌      | ❌         | ❌    | No option to override base URL.                                                                                                                        |
| Gemini CLI                        | ❌      | ❌         | ❌    | No Gemini API support. Upvote [this issue](https://github.com/coder/coder/issues/24804).                                                               |
| Antigravity                       | ❌      | ❌         | ❌    | No option to override base URL.                                                                                                                        |
|

*Legend: ✅ supported, ⚙️ requires AI Gateway Proxy, ❌ not supported, - not applicable.*

## Configure in-workspace tools

AI coding tools running inside a Coder workspace, such as IDE extensions, can be configured to use AI Gateway.

This section applies when you want template admins to preconfigure tools inside Coder workspaces. For tools running outside of a workspace, see [External and Desktop Clients](#external-and-desktop-clients).

While users can manually configure these tools with a long-lived API key, template admins can provide a more seamless experience by pre-configuring them. Admins can automatically inject the user's session token with `data.coder_workspace_owner.me.session_token` and the AI Gateway base URL into the workspace environment.

In this example, Claude Code respects these environment variables and will route all requests via AI Gateway.

```tf
data "coder_workspace_owner" "me" {}

data "coder_workspace" "me" {}

resource "coder_agent" "dev" {
    arch = "amd64"
    os   = "linux"
    dir  = local.repo_dir
    env = {
        ANTHROPIC_BASE_URL : "${data.coder_workspace.me.access_url}/api/v2/ai-gateway/anthropic",
        ANTHROPIC_AUTH_TOKEN : data.coder_workspace_owner.me.session_token
    }
    ... # other agent configuration
}
```

## External and Desktop Clients

You can also configure AI tools running outside of a Coder workspace, such as local IDE extensions or desktop applications, to connect to AI Gateway. Use the same settings as the in-workspace case, configure the [base URL](#base-urls) and authenticate with a Coder API token.

For base URL setup, the client machine must have network access to the gateway endpoint on your Coder deployment.
Clients using [AI Gateway Proxy](../ai-gateway-proxy/index.md) must be able to reach the proxy endpoint and trust its CA certificate.

Users can generate a long-lived API token from the Coder UI or CLI. Follow the instructions at [Sessions and API tokens](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself) to create one.

For headless scenarios, first [create a service account](../../../admin/users/headless-auth.md#create-a-service-account), then generate a long-lived token for it.

<details>
<summary>Example</summary>
For clients supporting [base URL](#base-urls), eg. [Claude Code](./claude-code.md):

```sh
export ANTHROPIC_BASE_URL="https://coder.example.com/api/v2/ai-gateway/anthropic"
export ANTHROPIC_AUTH_TOKEN="<your-coder-api-token>"
```

Replace `coder.example.com` with your Coder deployment URL.

For other clients setup [AI Gateway Proxy](../ai-gateway-proxy/index.md). Configure the proxy endpoint and [CA certificates](../ai-gateway-proxy/setup.md#environment-variables):

```sh
export HTTPS_PROXY="https://coder:<your-coder-api-token>@<proxy-host>:8888"
export SSL_CERT_FILE="/path/to/coder-ai-gateway-proxy-ca.pem"
```

For proxy setup details, see [AI Gateway Proxy setup](../ai-gateway-proxy/setup.md).

For BYOK and workspace template examples, see full [Claude Code](./claude-code.md) example.
</details>

For complete setup instructions, see the [supported client examples](#all-supported-clients).

## All Supported Clients

<children></children>

## Learn more

- [AI Gateway Authentication and BYOK](../auth.md)
- [AI Gateway Reference](../reference.md)

---

# Claude Code

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/claude-code

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

Claude Code can be configured using environment variables. All modes require a **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)** for authentication with AI Gateway.

## Centralized API Key

```sh
# AI Gateway base URL.
export ANTHROPIC_BASE_URL="<your-deployment-url>/api/v2/ai-gateway/anthropic"

# Your Coder API token, used for authentication with AI Gateway.
export ANTHROPIC_AUTH_TOKEN="<your-coder-api-token>"
```

<details>
<summary>Persistent config (<code>.claude/settings.json</code>)</summary>

Merge the following into `~/.claude/settings.json`, preserving your existing settings:

```json
{
  "env": {
    "ANTHROPIC_BASE_URL": "<your-deployment-url>/api/v2/ai-gateway/anthropic",
    "ANTHROPIC_AUTH_TOKEN": "<your-coder-api-token>"
  }
}
```

</details>

## BYOK (Personal API Key)

```sh
# AI Gateway base URL.
export ANTHROPIC_BASE_URL="<your-deployment-url>/api/v2/ai-gateway/anthropic"

# Your personal Anthropic API key, forwarded to Anthropic.
export ANTHROPIC_API_KEY="<your-anthropic-api-key>"

# Your Coder API token, used for authentication with AI Gateway.
export ANTHROPIC_CUSTOM_HEADERS="X-Coder-AI-Governance-Token: <your-coder-api-token>"

# Ensure no auth token is set so Claude Code uses the API key instead.
unset ANTHROPIC_AUTH_TOKEN
```

## BYOK (Claude Subscription)

```sh
# AI Gateway base URL.
export ANTHROPIC_BASE_URL="<your-deployment-url>/api/v2/ai-gateway/anthropic"

# Your Coder API token, used for authentication with AI Gateway.
export ANTHROPIC_CUSTOM_HEADERS="X-Coder-AI-Governance-Token: <your-coder-api-token>"

# Ensure no auth token is set so Claude Code uses subscription login instead.
unset ANTHROPIC_AUTH_TOKEN
```

When you run Claude Code, it will prompt you to log in with your Anthropic
account.

## Pre-configuring in Templates

Template admins can pre-configure Claude Code for a seamless experience. Admins can automatically inject the user's Coder session token and the AI Gateway base URL into the workspace environment.

```tf
module "claude-code" {
  source            = "registry.coder.com/coder/claude-code/coder"
  version           = "~> 5.2"
  agent_id          = coder_agent.main.id
  workdir           = "/path/to/project" # Set to your project directory
  enable_ai_gateway = true
}
```

Visit the [Claude Code module on the Coder Registry](https://registry.coder.com/modules/coder/claude-code) for the full list of inputs and outputs.

## VS Code Extension

The Claude Code VS Code extension is also supported.

1. If pre-configured in the workspace environment variables (as shown above), it typically respects them.
2. You may need to sign in once; afterwards, it respects the workspace environment variables.

**References:** [Claude Code Settings](https://docs.claude.com/en/docs/claude-code/settings#environment-variables)

---

# Codex CLI

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/codex

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

Codex CLI can be configured to use AI Gateway by setting up a custom model provider.

## Centralized API Key

To configure Codex CLI to use AI Gateway, set the following configuration options in your Codex configuration file (e.g., `~/.codex/config.toml`):

```toml
model_provider = "ai_gateway"

[model_providers.ai_gateway]
name = "AI Gateway"
base_url = "<your-deployment-url>/api/v2/ai-gateway/openai/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
```

To authenticate with AI Gateway, get your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)** and set it in your environment:

```sh
export OPENAI_API_KEY="<your-coder-api-token>"
```

Run Codex as usual. It will automatically use the `ai_gateway` model provider from your configuration.

## BYOK (Personal API Key)

Add the following to your Codex configuration file (e.g., `~/.codex/config.toml`):

```toml
model_provider = "ai_gateway"

[model_providers.ai_gateway]
name = "AI Gateway"
base_url = "<your-deployment-url>/api/v2/ai-gateway/openai/v1"
wire_api = "responses"
requires_openai_auth = true
env_http_headers = { "X-Coder-AI-Governance-Token" = "CODER_API_TOKEN" }
```

Set both environment variables:

```sh
# Your personal OpenAI API key, forwarded to OpenAI.
export OPENAI_API_KEY="<your-openai-api-key>"

# Your Coder API token, used for authentication with AI Gateway.
export CODER_API_TOKEN="<your-coder-api-token>"
```

## BYOK (ChatGPT Subscription)

> [!IMPORTANT]
> This flow requires a [ChatGPT provider](../providers.md#chatgpt) on
> the deployment. Without it, Codex requests fail with
> `404 route not supported: POST /chatgpt/v1/responses`.

Add the following to your Codex configuration file (e.g., `~/.codex/config.toml`):

```toml
model_provider = "ai_gateway"

[model_providers.ai_gateway]
name = "AI Gateway"
base_url = "<your-deployment-url>/api/v2/ai-gateway/chatgpt/v1"
wire_api = "responses"
requires_openai_auth = true
env_http_headers = { "X-Coder-AI-Governance-Token" = "CODER_API_TOKEN" }
```

> [!NOTE]
> The `base_url` uses `/ai-gateway/chatgpt/v1` instead of `/ai-gateway/openai/v1` to route requests through the ChatGPT provider.

Set your Coder API token and ensure `OPENAI_API_KEY` is not set:

```sh
# Your Coder API token, used for authentication with AI Gateway.
export CODER_API_TOKEN="<your-coder-api-token>"

# Ensure no OpenAI API key is set so Codex uses ChatGPT login instead.
unset OPENAI_API_KEY
```

When you run Codex, it will prompt you to log in with your ChatGPT account.

## Pre-configuring in Templates

If configuring within a Coder workspace, you can use the
[Codex CLI](https://registry.coder.com/modules/coder-labs/codex) module.

For the centralized API key flow, set `enable_ai_gateway`:

```tf
module "codex" {
  source            = "registry.coder.com/coder-labs/codex/coder"
  version           = "~> 5.3"
  agent_id          = coder_agent.main.id
  workdir           = "/path/to/project" # Set to your project directory
  enable_ai_gateway = true
}
```

For the ChatGPT subscription flow, pass the provider configuration
through `base_config_toml` and inject the Coder API token with a
`coder_env` resource. Users authenticate by running `codex login` with
their ChatGPT account:

```tf
resource "coder_env" "coder_api_token" {
  agent_id = coder_agent.main.id
  name     = "CODER_API_TOKEN"
  value    = data.coder_workspace_owner.me.session_token
}

module "codex" {
  source   = "registry.coder.com/coder-labs/codex/coder"
  version  = "~> 5.3"
  agent_id = coder_agent.main.id
  workdir  = "/path/to/project" # Set to your project directory

  base_config_toml = <<-TOML
    model_provider = "ai_gateway"

    [model_providers.ai_gateway]
    name = "AI Gateway"
    base_url = "${data.coder_workspace.me.access_url}/api/v2/ai-gateway/chatgpt/v1"
    wire_api = "responses"
    requires_openai_auth = true
    env_http_headers = { "X-Coder-AI-Governance-Token" = "CODER_API_TOKEN" }
  TOML
}
```

Do not set `OPENAI_API_KEY` in the workspace when using the ChatGPT
subscription flow, or Codex authenticates with the API key instead of
the ChatGPT login.

## Troubleshooting

### Codex falls back from WebSockets to HTTPS transport

Recent Codex CLI versions default to the WebSocket runtime for the
Responses API. AI Gateway does not support WebSocket transport, so each
request attempts a WebSocket connection and retries up to 5 times before
falling back to HTTPS. When this happens you will see:

```txt
Falling back from WebSockets to HTTPS transport.
```

The requests still succeed over HTTPS, but every turn waits through the
five failed WebSocket attempts first.

To stop Codex from attempting WebSockets, set `supports_websockets = false`
in your AI Gateway provider block in `~/.codex/config.toml`:

```toml
model_provider = "ai_gateway"

[model_providers.ai_gateway]
name = "AI Gateway"
base_url = "<your-deployment-url>/api/v2/ai-gateway/openai/v1"
wire_api = "responses"
supports_websockets = false
```

This forces the HTTPS transport directly and removes the fallback delay.

**References:** [Codex CLI Configuration](https://developers.openai.com/codex/config-reference)

---

# Xum

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/xum

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

Xum (formerly Mux) makes it easy to run parallel coding agents, each with its own isolated workspace, from your browser or desktop; it is open source and provider-agnostic.

Xum can be configured to route OpenAI- and Anthropic-compatible traffic through AI Gateway by setting a custom provider base URL and using a Coder-issued token for authentication.

## Prerequisites

- AI Gateway is enabled on your Coder deployment.
- A **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.

## Configuration

<div class="tabs">

### OpenAI

1. Open Xum settings (`Cmd+,` / `Ctrl+,`).
2. Go to **Providers** → **OpenAI**.
3. Set **API Key** to your Coder API token.
4. Set **Base URL** to `https://coder.example.com/api/v2/ai-gateway/openai/v1`.

### Anthropic

1. Open Xum settings (`Cmd+,` / `Ctrl+,`).
2. Go to **Providers** → **Anthropic**.
3. Set **API Key** to your Coder API token.
4. Set **Base URL** to `https://coder.example.com/api/v2/ai-gateway/anthropic`.

</div>

_Replace `coder.example.com` with your Coder deployment URL._

## Environment variables

Xum reads provider configuration from its settings UI and also from environment variables.
Environment variables are useful in CI or when running Xum inside a Coder workspace.

> [!NOTE]
> Xum treats environment variables as a fallback when a provider is not configured in settings.
> If you have already configured a provider in the UI, clear it (or update it) for env vars to take effect.

```sh
# OpenAI-compatible traffic (GPT, Codex, etc.)
export OPENAI_API_KEY="<your-coder-api-token>"
export OPENAI_BASE_URL="https://coder.example.com/api/v2/ai-gateway/openai/v1"

# Anthropic-compatible traffic (Claude, etc.)
export ANTHROPIC_API_KEY="<your-coder-api-token>"
export ANTHROPIC_BASE_URL="https://coder.example.com/api/v2/ai-gateway/anthropic"
```

## Run Xum in a Coder workspace

To run Xum inside a Coder workspace (for example, as a Coder app), you can install it with the [`mux` module](https://registry.coder.com/modules/coder/mux) (still published under its pre-rename name) and pre-configure AI Gateway via environment variables on the workspace agent:

```tf
data "coder_workspace" "me" {}

data "coder_workspace_owner" "me" {}

resource "coder_agent" "main" {
  # ... other agent configuration
  env = {
    OPENAI_API_KEY     = data.coder_workspace_owner.me.session_token
    OPENAI_BASE_URL    = "${data.coder_workspace.me.access_url}/api/v2/ai-gateway/openai/v1"
    ANTHROPIC_API_KEY  = data.coder_workspace_owner.me.session_token
    ANTHROPIC_BASE_URL = "${data.coder_workspace.me.access_url}/api/v2/ai-gateway/anthropic"
  }
}

module "mux" {
  source   = "registry.coder.com/coder/mux/coder"
  version  = "~> 1.5"
  agent_id = coder_agent.main.id
}
```

## Advanced: providers.jsonc

If you prefer a file-based config, edit `~/.xum/providers.jsonc`:

```json
{
  "openai": {
    "apiKey": "<your-coder-api-token>",
    "baseUrl": "https://coder.example.com/api/v2/ai-gateway/openai/v1"
  },
  "anthropic": {
    "apiKey": "<your-coder-api-token>",
    "baseUrl": "https://coder.example.com/api/v2/ai-gateway/anthropic"
  }
}
```

**References:** [Xum provider environment variables](https://xum.coder.com/config/providers#environment-variables)

---

# OpenCode

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/opencode

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

OpenCode supports both OpenAI and Anthropic models and can be configured to use AI Gateway by setting custom base URLs for each provider.

## Centralized API Key

You can configure OpenCode to connect to AI Gateway by setting the following configuration options in your OpenCode configuration file (e.g., `~/.config/opencode/opencode.json`):

```json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "options": {
        "baseURL": "https://coder.example.com/api/v2/ai-gateway/anthropic/v1"
      }
    },
    "openai": {
      "options": {
        "baseURL": "https://coder.example.com/api/v2/ai-gateway/openai/v1"
      }
    }
  }
}
```

To authenticate with AI Gateway, get your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**, then run:

```sh
opencode auth login
```

Select `anthropic` (and repeat for `openai` if needed), then paste your Coder API token when prompted for the API key.

## BYOK (Personal API Key)

Set the following in `~/.config/opencode/opencode.json`, including the `X-Coder-AI-Governance-Token` header with your Coder API token:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "anthropic": {
      "options": {
        "baseURL": "https://coder.example.com/api/v2/ai-gateway/anthropic/v1",
        "headers": {
          "X-Coder-AI-Governance-Token": "<your-coder-api-token>"
        }
      }
    },
    "openai": {
      "options": {
        "baseURL": "https://coder.example.com/api/v2/ai-gateway/openai/v1",
        "headers": {
          "X-Coder-AI-Governance-Token": "<your-coder-api-token>"
        }
      }
    }
  }
}
```

Set your personal API keys by running:

```sh
opencode auth login
```

Select `anthropic` (and repeat for `openai` if needed), then paste the corresponding API key you obtained earlier when prompted.

## Custom models through Bedrock Mantle

You can use OpenCode with custom model IDs through a [Bedrock Mantle provider](../providers.md#mantle) configured by your Coder administrator.
AI Gateway signs requests with AWS credentials centrally, so you only need a [Coder API token](../auth.md#authenticate-ai-clients) in OpenCode.
Use a custom provider in OpenCode that matches your model's API, rather than its native Amazon Bedrock integration.
The following example uses Astra with the Responses API.
For other models, choose the SDK package that matches the API:

| Model API          | OpenCode `npm` package      |
|--------------------|-----------------------------|
| Responses          | `@ai-sdk/openai`            |
| Chat Completions   | `@ai-sdk/openai-compatible` |
| Anthropic Messages | `@ai-sdk/anthropic`         |

1. In a shell where you're logged in with the Coder CLI, set your token:

   ```sh
   export CODER_TOKEN="$(coder login token)"
   ```

   This command sets `CODER_TOKEN` without printing the token.

2. Merge the following configuration into `~/.config/opencode/opencode.json`:

   ```json
   {
     "$schema": "https://opencode.ai/config.json",
     "provider": {
       "coder-mantle": {
         "npm": "@ai-sdk/openai",
         "name": "Coder Bedrock Mantle",
         "options": {
           "baseURL": "https://coder.example.com/api/v2/ai-gateway/bedrock-provider-name/v1",
           "apiKey": "{env:CODER_TOKEN}"
         },
         "models": {
           "astra": {
             "id": "openai.gpt-6-astra",
             "name": "Astra",
             "tool_call": true
           }
         }
       }
     },
     "model": "coder-mantle/astra",
     "small_model": "coder-mantle/astra"
   }
   ```

   Replace `coder.example.com` with your AI Gateway host and `bedrock-provider-name` with the provider name configured in Coder.
   Keep the `/v1` suffix.
   Replace `openai.gpt-6-astra` with the exact Mantle model ID available in your AWS account and region.
   Set `npm` to the SDK package for that model's API.
   Set `tool_call` to `true` only if the model supports tools.

   The `astra` key is a local model alias in OpenCode.
   The `id` field is the model ID sent upstream.
   Preserve any vendor prefix in the model ID, such as `openai.` or `anthropic.`.
   You can add more entries under `models` to use model IDs outside OpenCode's built-in catalog.

   The optional `model` and `small_model` fields select the default model and the model for lightweight tasks, such as title generation.
   This example uses Astra for both, so both types of request use the same gateway provider.
   To use a different small model, add its entry under `models` and update `small_model` to `coder-mantle/<model-alias>`.

3. Start OpenCode from the same shell:

   ```sh
   opencode
   ```

   OpenCode uses the configured Astra model through AI Gateway.

All three SDK packages use the same gateway base URL ending in `/v1`.
The selected SDK sends requests to `/v1/responses`, `/v1/chat/completions`, or `/v1/messages`.
Use a model that supports the selected API.
For more configuration options, refer to [OpenCode custom providers](https://opencode.ai/docs/providers/#custom-provider).

**References:** [OpenCode Documentation](https://opencode.ai/docs/providers/#config)

---

# Factory

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/factory

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

Factort's Droid agent can be configured to use AI Gateway by setting up custom models for OpenAI and Anthropic.

## Centralized API Key

1. Open `~/.factory/settings.json` (create it if it does not exist).
2. Add a `customModels` entry for each provider you want to use with AI Gateway.
3. Replace `coder.example.com` with your Coder deployment URL.
4. Use a **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)** for `apiKey`.

```json
{
  "customModels": [
    {
      "model": "claude-sonnet-4-5-20250929",
      "displayName": "Claude (Coder AI Gateway)",
      "baseUrl": "https://coder.example.com/api/v2/ai-gateway/anthropic",
      "apiKey": "<your-coder-api-token>",
      "provider": "anthropic",
      "maxOutputTokens": 8192
    },
    {
      "model": "gpt-5.2-codex",
      "displayName": "GPT (Coder AI Gateway)",
      "baseUrl": "https://coder.example.com/api/v2/ai-gateway/openai/v1",
      "apiKey": "<your-coder-api-token>",
      "provider": "openai",
      "maxOutputTokens": 16384
    }
  ]
}
```

## BYOK (Personal API Key)

1. Open `~/.factory/settings.json` (create it if it does not exist).
2. Add a `customModels` entry for each provider you want to use with AI Gateway.
3. Replace `coder.example.com` with your Coder deployment URL.
4. Use your personal API key for `apiKey`.
5. Set the `X-Coder-AI-Governance-Token` header to your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.

```json
{
  "customModels": [
    {
      "model": "claude-sonnet-4-5-20250929",
      "displayName": "Claude (Coder AI Gateway)",
      "baseUrl": "https://coder.example.com/api/v2/ai-gateway/anthropic",
      "apiKey": "<your-anthropic-api-key>",
      "provider": "anthropic",
      "maxOutputTokens": 8192,
      "extraHeaders": {
        "X-Coder-AI-Governance-Token": "<your-coder-api-token>"
      }
    },
    {
      "model": "gpt-5.2-codex",
      "displayName": "GPT (Coder AI Gateway)",
      "baseUrl": "https://coder.example.com/api/v2/ai-gateway/openai/v1",
      "apiKey": "<your-openai-api-key>",
      "provider": "openai",
      "maxOutputTokens": 16384,
      "extraHeaders": {
        "X-Coder-AI-Governance-Token": "<your-coder-api-token>"
      }
    }
  ]
}
```

**References:** [Factory BYOK OpenAI & Anthropic](https://docs.factory.ai/cli/byok/openai-anthropic)

---

# Cline

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/cline

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

Cline supports both OpenAI and Anthropic models and can be configured to use AI Gateway by setting providers.

## Configuration

To configure Cline to use AI Gateway, follow these steps:
![Cline Settings](../../../images/aibridge/clients/cline-setup.png)

## Centralized API Key

<div class="tabs">

### OpenAI Compatible

1. Open Cline in VS Code.
1. Go to **Settings**.
1. **API Provider**: Select **OpenAI Compatible**.
1. **Base URL**: Enter `https://coder.example.com/api/v2/ai-gateway/openai/v1`.
1. **OpenAI Compatible API Key**: Enter your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.
1. **Model ID** (Optional): Enter the model you wish to use (e.g., `gpt-5.2-codex`).

![Cline OpenAI Settings](../../../images/aibridge/clients/cline-openai.png)

### Anthropic

1. Open Cline in VS Code.
1. Go to **Settings**.
1. **API Provider**: Select **Anthropic**.
1. **Anthropic API Key**: Enter your **Coder API token**.
1. **Base URL**: Enter `https://coder.example.com/api/v2/ai-gateway/anthropic` after checking **_Use custom base URL_**.
1. **Model ID** (Optional): Select your desired Claude model.

![Cline Anthropic Settings](../../../images/aibridge/clients/cline-anthropic.png)

</div>

## BYOK (Personal API Key)

<div class="tabs">

### OpenAI Compatible

1. Open Cline in VS Code.
1. Go to **Settings**.
1. **API Provider**: Select **OpenAI Compatible**.
1. **Base URL**: Enter `https://coder.example.com/api/v2/ai-gateway/openai/v1`.
1. **OpenAI Compatible API Key**: Enter your personal OpenAI API key.
1. **Model ID** (Optional): Enter the model you wish to use (e.g., `gpt-5.2-codex`).
1. **Custom Headers**: Add `X-Coder-AI-Governance-Token` with your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.

![Cline BYOK OpenAI Settings](../../../images/aibridge/clients/cline-byok-openai.png)

</div>

**References:** [Cline Configuration](https://github.com/cline/cline)

---

# Kilo Code

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/kilo-code

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

Kilo Code allows you to configure providers via the UI and can be set up to use AI Gateway.

## Centralized API Key

<div class="tabs">

### OpenAI Compatible

1. Open Kilo Code in VS Code.
1. Go to **Settings**.
1. **Provider**: Select **OpenAI**.
1. **Base URL**: Enter `https://coder.example.com/api/v2/ai-gateway/openai/v1`.
1. **API Key**: Enter your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.
1. **Model ID**: Enter the model you wish to use (e.g., `gpt-5.2-codex`).

![Kilo Code OpenAI Settings](../../../images/aibridge/clients/kilo-code-openai.png)

### Anthropic

1. Open Kilo Code in VS Code.
1. Go to **Settings**.
1. **Provider**: Select **Anthropic**.
1. **Base URL**: Enter `https://coder.example.com/api/v2/ai-gateway/anthropic`.
1. **API Key**: Enter your **Coder API token**.
1. **Model ID**: Select your desired Claude model.

![Kilo Code Anthropic Settings](../../../images/aibridge/clients/kilo-code-anthropic.png)

</div>

## BYOK (Personal API Key)

> [!NOTE]
> Kilo Code supports sending custom headers, but the integration does not currently work reliably with AI Gateway.

**References:** [Kilo Code Configuration](https://kilocode.ai/docs/ai-providers/openai-compatible)

---

# VS Code

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/vscode

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

VS Code's native chat can be configured to use AI Gateway via the **Custom Endpoint** language model provider (VS Code 1.122+, Stable). GitHub sign-in is not required, so this works in air-gapped or restricted environments.

## Setup

Requires VS Code 1.122+ and the [GitHub Copilot Chat extension](https://marketplace.visualstudio.com/items?itemName=GitHub.copilot-chat).

For each provider below, the setup steps are:

1. Open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P` on Mac) and run **Chat: Manage Language Models**.
1. Select **Add** → **Custom Endpoint**.
1. Enter a **group name**, **display name**, your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)** as the API key, and the **API type** shown below.
1. To add or edit models, select the gear icon next to the provider in the Language Models view to open `chatLanguageModels.json`.

> [!IMPORTANT]
> Enter your API token through the UI. VS Code stores it securely and inserts a reference like `${input:chat.lm.secret.XXXXX}` into the JSON. Do not paste your token directly into the JSON file.

_Replace `coder.example.com` with your Coder deployment URL. Model IDs must match what is configured in your AI Gateway._

### OpenAI-compatible models

Set **API type** to `responses`.

```json
{
    "name": "Coder (OpenAI)",
    "vendor": "customendpoint",
    "apiKey": "${input:chat.lm.secret.XXXXX}",
    "apiType": "responses",
    "models": [
        {
            "id": "gpt-5.5",
            "name": "GPT 5.5",
            "url": "https://coder.example.com/api/v2/ai-gateway/openai",
            "toolCalling": true,
            "vision": true,
            "thinking": true,
            "streaming": true,
            "maxInputTokens": 272000,
            "maxOutputTokens": 128000
        }
    ]
}
```

### Anthropic models

Set **API type** to `messages`.

```json
{
    "name": "Coder (Anthropic)",
    "vendor": "customendpoint",
    "apiKey": "${input:chat.lm.secret.XXXXX}",
    "apiType": "messages",
    "models": [
        {
            "id": "claude-sonnet-4.6",
            "name": "Claude Sonnet 4.6",
            "url": "https://coder.example.com/api/v2/ai-gateway/anthropic",
            "toolCalling": true,
            "vision": true,
            "thinking": true,
            "streaming": true,
            "maxInputTokens": 1000000,
            "maxOutputTokens": 64000
        }
    ]
}
```

**References:** [VS Code - Bring your own language model](https://code.visualstudio.com/docs/copilot/customization/language-models)

---

# JetBrains

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/jetbrains

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

JetBrains IDE (IntelliJ IDEA, PyCharm, WebStorm, etc.) support AI Gateway via the [third-party model configuration](https://www.jetbrains.com/help/ai-assistant/use-custom-models.html#provide-your-own-api-key) feature.

## Prerequisites

* [**JetBrains AI Assistant**](https://www.jetbrains.com/help/ai-assistant/installation-guide-ai-assistant.html): Installed and enabled.
* **Authentication**: Your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.

## Centralized API Key

1. **Open Settings**: Go to **Settings** > **Tools** > **AI Assistant** > **Models & API Keys**.
1. **Configure Provider**: Go to **Third-party AI providers**.
1. **Choose Provider**: Choose **OpenAI-compatible**.
1. **URL**: `https://coder.example.com/api/v2/ai-gateway/openai/v1`
1. **API Key**: Paste your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.
1. **Apply**: Select **Apply** and **OK**.

![JetBrains AI Assistant Settings](../../../images/aibridge/clients/jetbrains-ai-settings.png)

<a id="using-the-ai-assistant"></a>

## Use the AI Assistant

1. Go back to **AI Chat** on theleft side bar and choose **Chat**.
1. In the Model dropdown, select the desired model (e.g., `gpt-5.2`).

![JetBrains AI Assistant Chat](../../../images/aibridge/clients/jetbrains-ai-chat.png)

You can now use the AI Assistant chat with the configured provider.

> [!NOTE]
>
> * JetBrains AI Assistant currently only supports OpenAI-compatible endpoints. There is an open [issue](https://youtrack.jetbrains.com/issue/LLM-22740) tracking support for Anthropic.
> * JetBrains AI Assistant may not support all models that support OpenAI's `/chat/completions` endpoint in Chat mode.
> * JetBrains AI Assistant does not send an identifying user agent, so AI Gateway records these sessions with the client `Unknown`. Usage, tokens, and audit data are still captured.

## BYOK (Personal API Key)

> [!NOTE]
> At the time of writing, JetBrains AI Assistant does not support sending custom headers, so BYOK mode is not available.

**References:** [Use custom models with JetBrains AI Assistant](https://www.jetbrains.com/help/ai-assistant/use-custom-models.html#provide-your-own-api-key)

---

# Junie

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/junie

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

[Junie CLI](https://junie.jetbrains.com/docs/junie-cli.html) supports AI Gateway
through [custom model profiles](https://junie.jetbrains.com/docs/custom-llm-models.html#using-custom-models).

| Provider  | API type          | Endpoint                 |
|-----------|-------------------|--------------------------|
| OpenAI    | `OpenAIResponses` | `/openai/v1/responses`   |
| Anthropic | `Anthropic`       | `/anthropic/v1/messages` |

For Junie inside JetBrains IDEs, refer to [JetBrains IDEs](./jetbrains.md).

## Prerequisites

* **Junie CLI**: Installed with `curl -fsSL https://junie.jetbrains.com/install.sh | bash`.
* **Authentication**: Your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.

## Centralized API Key

Junie discovers custom model profiles from JSON files in two locations:

| Scope   | Location                 |
|---------|--------------------------|
| User    | `~/.junie/models/*.json` |
| Project | `.junie/models/*.json`   |

The file name without the `.json` extension is the profile ID.

Create `~/.junie/models/ai-gateway.json` for the OpenAI endpoint:

```json
{
  "id": "gpt-5.5",
  "baseUrl": "https://coder.example.com/api/v2/ai-gateway/openai/v1/responses",
  "apiType": "OpenAIResponses",
  "apiKey": "${CODER_API_TOKEN}",
  "fasterModel": { "id": "gpt-5.4-mini" }
}
```

Or for the Anthropic endpoint:

```json
{
  "id": "claude-sonnet-5",
  "baseUrl": "https://coder.example.com/api/v2/ai-gateway/anthropic/v1/messages",
  "apiType": "Anthropic",
  "apiKey": "${CODER_API_TOKEN}",
  "fasterModel": { "id": "claude-haiku-4-5-20251001" }
}
```

*Replace `coder.example.com` with your Coder deployment URL.*

> [!NOTE]
> `baseUrl` is the complete endpoint URL. Junie does not append a path to it, so
> include `/v1/responses` for `OpenAIResponses` and `/v1/messages` for
> `Anthropic`.

Junie resolves `${VAR}` references in `apiKey` and `extraHeaders` from the
environment, so the token never has to be written to disk:

```sh
export CODER_API_TOKEN=$(coder login token)
```

Run Junie with the profile:

```sh
junie --model custom:ai-gateway
```

Custom profiles also appear in the model selection list of the interactive TUI
and in the `/model` slash command.

## BYOK (Personal API Key)

Junie supports custom headers, so BYOK works by sending your personal provider
key as the API key and the Coder API token as the governance token:

```json
{
  "id": "gpt-5.5",
  "baseUrl": "https://coder.example.com/api/v2/ai-gateway/openai/v1/responses",
  "apiType": "OpenAIResponses",
  "apiKey": "${OPENAI_API_KEY}",
  "extraHeaders": { "X-Coder-AI-Governance-Token": "${CODER_API_TOKEN}" }
}
```

Set both environment variables:

```sh
# Your personal provider API key, forwarded to the upstream provider.
export OPENAI_API_KEY="<your-openai-api-key>"

# Your Coder API token, used for authentication with AI Gateway.
export CODER_API_TOKEN="<your-coder-api-token>"
```

## Pre-configuring in Templates

Commit the profile to your repository at `.junie/models/ai-gateway.json` and
inject the token from the template, so users get a working configuration without
manual setup:

```tf
data "coder_workspace_owner" "me" {}

data "coder_workspace" "me" {}

resource "coder_env" "coder_api_token" {
  agent_id = coder_agent.main.id
  name     = "CODER_API_TOKEN"
  value    = data.coder_workspace_owner.me.session_token
}
```

Reference the deployment URL in the profile with
`${data.coder_workspace.me.access_url}/api/v2/ai-gateway/openai/v1/responses`
if you generate the file from the template instead of committing it.

**References:** [Junie custom LLMs](https://junie.jetbrains.com/docs/custom-llm-models.html#using-custom-models)

---

# Zed

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/zed

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

Zed IDE supports AI Gateway via its `language_models` configuration in `settings.json`.

## Centralized API Key

To configure Zed to use AI Gateway, you need to edit your `settings.json` file. You can access this by pressing `Cmd/Ctrl + ,` or opening the command palette and searching for "Open Settings".

You can configure both Anthropic and OpenAI providers to point to AI Gateway.

```json
{
  "language_models": {
    "anthropic": {
      "api_url": "https://coder.example.com/api/v2/ai-gateway/anthropic",
    },
    "openai": {
      "api_url": "https://coder.example.com/api/v2/ai-gateway/openai/v1",
    },
  },
  // optional settings to set favorite models for the AI
  "agent": {
    "favorite_models": [
      {
        "provider": "anthropic",
        "model": "claude-sonnet-4-5-thinking-latest"
      },
      {
        "provider": "openai",
        "model": "gpt-5.2-codex"
      }
    ],
  },
}
```

*Replace `coder.example.com` with your Coder deployment URL.*

> [!NOTE]
> These settings and environment variables need to be configured from client side. Zed currently does not support reading these settings from remote configuration. See this [feature request](https://github.com/zed-industries/zed/discussions/47058) for more details.

## Authentication

Zed requires an API key for these providers. For AI Gateway, this key is your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)**.

You can set this in two ways:

<div class="tabs">

### Zed UI

1. Open the **Assistant Panel** (right sidebar).
1. Select **Configuration** or the settings icon.
1. Select your provider ("Anthropic" or "OpenAI").
1. Paste your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)** for the API Key.

### Environment Variables

1. Set `ANTHROPIC_API_KEY` and `OPENAI_API_KEY` to your **[Coder API token](../../../admin/users/sessions-tokens.md#generate-a-long-lived-api-token-on-behalf-of-yourself)** in the environment where you launch Zed.

</div>

## BYOK (Personal API Key)

> [!NOTE]
> At the time of writing, Zed Agent does not support sending custom headers, so BYOK mode is not available.

**References:** [Configuring Zed - Language Models](https://zed.dev/docs/reference/all-settings#language-models)

---

# GitHub Copilot

Source: https://coder.com/docs/ai-coder/ai-gateway/clients/copilot

> [!NOTE]
> AI Gateway is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

[GitHub Copilot](https://github.com/features/copilot) is an AI coding assistant that doesn't support custom base URLs but does respect proxy configurations.
This makes it compatible with [AI Gateway Proxy](../ai-gateway-proxy/index.md), which integrates with [AI Gateway](../index.md) for full access to auditing and governance features.
To use Copilot with AI Gateway, make sure AI Gateway Proxy is properly configured, see [AI Gateway Proxy Setup](../ai-gateway-proxy/setup.md) for instructions.

Copilot uses **per-user tokens** tied to GitHub accounts rather than a shared API key.
Users must still authenticate with GitHub to use Copilot.

For general information about GitHub Copilot, see the [GitHub Copilot documentation](https://docs.github.com/en/copilot).

For general client configuration requirements, see [AI Gateway Proxy Client Configuration](../ai-gateway-proxy/setup.md#client-configuration).
The sections below cover Copilot-specific setup for each client.

For provider configuration (admin), see [GitHub Copilot provider setup](../providers.md#github-copilot).

## Copilot CLI

For installation instructions, see [GitHub Copilot CLI documentation](https://docs.github.com/en/copilot/how-tos/copilot-cli/install-copilot-cli).

### Proxy configuration

Set the `HTTPS_PROXY` environment variable:

```sh
export HTTPS_PROXY="https://coder:${CODER_API_TOKEN}@<proxy-host>:8888"
```

Replace `<proxy-host>` with your AI Gateway Proxy hostname.

Note: if [TLS is not enabled](../ai-gateway-proxy/setup.md#proxy-tls-configuration) on the proxy, replace `https://` with `http://` in the proxy URL.

### CA certificate trust

Copilot CLI is built on Node.js and uses the `NODE_EXTRA_CA_CERTS` environment variable for custom certificates:

```sh
export NODE_EXTRA_CA_CERTS="/path/to/coder-ai-gateway-proxy-ca.pem"
```

Refer to [Client Configuration CA certificate trust](../ai-gateway-proxy/setup.md#trust-the-ca-certificate) for details on how to obtain the certificate file.

When [TLS is enabled](../ai-gateway-proxy/setup.md#proxy-tls-configuration) on the proxy, combine the MITM CA certificate and the TLS certificate into a single file:

```sh
cat coder-ai-gateway-proxy-ca.pem listener.crt > combined-ca.pem
export NODE_EXTRA_CA_CERTS="/path/to/combined-ca.pem"
```

Copilot CLI may start MCP server processes that use runtimes other than Node.js (e.g. Go).
These processes inherit environment variables like `HTTPS_PROXY` but may not respect `NODE_EXTRA_CA_CERTS`.
Adding the TLS certificate to the [system trust store](../ai-gateway-proxy/setup.md#system-trust-store) ensures all processes trust it.

## VS Code Copilot Extension

For installation instructions, see [Installing the GitHub Copilot extension in VS Code](https://docs.github.com/en/copilot/how-tos/set-up/install-copilot-extension?tool=vscode).

### Proxy configuration

You can configure the proxy using environment variables or VS Code settings.
For environment variables, visit [AI Gateway Proxy client configuration](../ai-gateway-proxy/setup.md#configure-the-proxy).

Alternatively, you can configure the proxy directly in VS Code settings:

1. Open Settings (`Ctrl+,` for Windows or `Cmd+,` for macOS)
1. Search for `HTTP: Proxy`
1. Set the proxy URL using the format `https://coder:<CODER_API_TOKEN>@<proxy-host>:8888`

Or add directly to your `settings.json`:

```json
{
    "http.proxy": "https://coder:<CODER_API_TOKEN>@<proxy-host>:8888"
}
```

Note: if [TLS is not enabled](../ai-gateway-proxy/setup.md#proxy-tls-configuration) on the proxy, replace `https://` with `http://` in the proxy URL.

The `http.proxy` setting is used for both HTTP and HTTPS requests.
Replace `<proxy-host>` with your AI Gateway Proxy hostname and `<CODER_API_TOKEN>` with your Coder API token.

Restart VS Code for changes to take effect.

For more details, see [Configuring proxy settings for Copilot](https://docs.github.com/en/copilot/how-tos/configure-personal-settings/configure-network-settings?tool=vscode) in the GitHub documentation.

### CA certificate trust

Add the AI Gateway Proxy CA certificate to your operating system's trust store.
By default, VS Code loads system certificates, controlled by the `http.systemCertificates` setting.

Check out [Client Configuration CA certificate trust](../ai-gateway-proxy/setup.md#trust-the-ca-certificate) for details on how to obtain the certificate file.

When [TLS is enabled](../ai-gateway-proxy/setup.md#proxy-tls-configuration) on the proxy, add the TLS certificate to the system trust store as well.

### Coder Remote extension

When connecting to a Coder workspace with the [Coder extension](https://marketplace.visualstudio.com/items?itemName=coder.coder-remote), the Copilot extension runs inside the Coder workspace and not on your local machine.
This means proxy and certificate configuration must be done in the Coder workspace environment.

When [TLS is enabled](../ai-gateway-proxy/setup.md#proxy-tls-configuration) on the proxy, add the TLS certificate to the workspace's system trust store as well.

#### Proxy configuration

Configure the proxy in VS Code's remote settings:

1. [Connect to your Coder workspace](../../../user-guides/workspace-access/vscode.md)
1. Open Settings (`Ctrl+,` for Windows or `Cmd+,` for macOS)
1. Select the **Remote** tab
1. Search for `HTTP: Proxy`
1. Set the proxy URL using the format `https://coder:<CODER_API_TOKEN>@<proxy-host>:8888`

Note: if [TLS is not enabled](../ai-gateway-proxy/setup.md#proxy-tls-configuration) on the proxy, replace `https://` with `http://` in the proxy URL.

Replace `<proxy-host>` with your AI Gateway Proxy hostname and `<CODER_API_TOKEN>` with your Coder API token.

#### CA certificate trust

Since the Copilot extension runs inside the Coder workspace, add the [AI Gateway Proxy CA certificate](../ai-gateway-proxy/setup.md#trust-the-ca-certificate) to the Coder workspace's system trust store.
See [System trust store](../ai-gateway-proxy/setup.md#system-trust-store) for instructions on how to do this on Linux.

Restart VS Code for changes to take effect.

## JetBrains IDEs

For installation instructions, see [Installing the GitHub Copilot extension in JetBrains IDE](https://docs.github.com/en/copilot/how-tos/set-up/install-copilot-extension?tool=jetbrains).

### Proxy configuration

Configure the proxy directly in JetBrains IDE settings:

1. Open Settings (`Ctrl+Alt+S` for Windows or `Cmd+,` for macOS)
1. Navigate to `Appearance & Behavior` > `System Settings` > `HTTP Proxy`
1. Select `Manual proxy configuration` and `HTTP`
1. Enter the proxy hostname and port (default: 8888)
1. Select `Proxy authentication` and enter:
   1. Login: `coder` (this value is ignored)
   1. Password: Your Coder API token
   1. Check `Remember` to save the password
1. Restart the IDE for changes to take effect

For more details, see [Configuring proxy settings for Copilot](https://docs.github.com/en/copilot/how-tos/configure-personal-settings/configure-network-settings?tool=jetbrains) in the GitHub documentation.

### CA certificate trust

Add the AI Gateway Proxy CA certificate to your operating system's trust store.
If the certificate is in the system trust store, no additional IDE configuration is needed.

When [TLS is enabled](../ai-gateway-proxy/setup.md#proxy-tls-configuration) on the proxy, add the TLS certificate to the system trust store as well, or add it under `Accepted certificates` in the IDE settings below.

Alternatively, you can configure the IDE to accept the certificate:

1. Open Settings (`Ctrl+Alt+S` for Windows or `Cmd+,` for macOS)
1. Navigate to `Appearance & Behavior` > `System Settings` > `Server Certificates`
1. Under `Accepted certificates`, select `+` and select the CA certificate file
1. Check `Accept non-trusted certificates automatically`
1. Restart the IDE for changes to take effect

For more details, see [Trusted root certificates](https://www.jetbrains.com/help/idea/ssl-certificates.html) in the JetBrains documentation.

See [Client Configuration CA certificate trust](../ai-gateway-proxy/setup.md#trust-the-ca-certificate) for details on how to obtain the certificate file.

---

# MCP

Source: https://coder.com/docs/ai-coder/ai-gateway/mcp

> [!NOTE]
> AI Gateway is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

<!-- -->

> [!WARNING]
> Injected MCP in AI Gateway is deprecated.
> It remains functional and will not be removed until
> the new implementation is released. Only critical
> security-related patches will be made.

[Model Context Protocol (MCP)](https://modelcontextprotocol.io/docs/getting-started/intro) is a mechanism for connecting AI applications to external systems.

AI Gateway can connect to MCP servers and inject tools automatically, enabling you to centrally manage the list of tools you wish to grant your users.

> [!NOTE]
> Only MCP servers which support OAuth2 Authorization are supported currently.
>
> [_Streamable HTTP_](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports) is the only supported transport currently. In future releases we will support the (now deprecated) [_Server-Sent Events_](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#backwards-compatibility) transport.

AI Gateway makes use of [External Auth](../../admin/external-auth/index.md) applications, as they define OAuth2 connections to upstream services. If your External Auth application hosts a remote MCP server, you can configure AI Gateway to connect to it, retrieve its tools and inject them into requests automatically - all while using each individual user's access token.

For example, GitHub has a [remote MCP server](https://github.com/github/github-mcp-server?tab=readme-ov-file#remote-github-mcp-server) and we can use it as follows.

```sh
CODER_EXTERNAL_AUTH_0_TYPE=github
CODER_EXTERNAL_AUTH_0_CLIENT_ID=...
CODER_EXTERNAL_AUTH_0_CLIENT_SECRET=...
# Tell AI Gateway where it can find this service's remote MCP server.
CODER_EXTERNAL_AUTH_0_MCP_URL=https://api.githubcopilot.com/mcp/
```

Refer to the diagram in [Embedded gateway](./reference.md#embedded-gateway) for more information.

You can also control which tools are injected by using an allow and/or a deny regular expression on the tool names:

```dotenv
CODER_EXTERNAL_AUTH_0_MCP_TOOL_ALLOW_REGEX=(.+_gist.*)
CODER_EXTERNAL_AUTH_0_MCP_TOOL_DENY_REGEX=(create_gist)
```

In the above example, all tools containing `_gist` in their name will be allowed, but `create_gist` is denied.

The logic works as follows:

- If neither the allow/deny patterns are defined, all tools will be injected.
- The deny pattern takes precedence.
- If only a deny pattern is defined, all tools are injected except those explicitly denied.

In the above example, if you prompted your AI model with "list your available github tools by name", it would reply something like:

> Certainly! Here are the GitHub-related tools that I have available:
>
> ```text
> 1. bmcp_github_update_gist
> 2. bmcp_github_list_gists
> ```

AI Gateway marks automatically injected tools with a prefix `bmcp_` ("bridged MCP"). It also namespaces all tool names by the ID of their associated External Auth application (in this case `github`).

## Tool Injection

If a model decides to invoke a tool with a `bmcp_` prefix and AI Gateway has a connection to the related MCP server, AI Gateway invokes the tool.
AI Gateway passes the tool result back to the upstream AI provider, and this loop continues until the model has all required data.
These inner loops are not relayed back to the client.
The client only sees the result of the loop.
Injected MCP works with both embedded and standalone gateways.
Control connection provides each standalone replica with the required configuration and access tokens.
Refer to [Deployment topologies](./reference.md#deployment-topologies) for more information.

In contrast, tools which are defined by the client (i.e. the [`Bash` tool](https://docs.claude.com/en/docs/claude-code/settings#tools-available-to-claude) defined by _Claude Code_) cannot be invoked by AI Gateway, and the tool call from the model will be relayed to the client, after which it will invoke the tool.

If you have [Coder MCP Server](../mcp-server.md) enabled, as well as have `CODER_AI_GATEWAY_INJECT_CODER_MCP_TOOLS=true` set, Coder's MCP tools will be injected into intercepted requests.

### Troubleshooting

- **Too many tools**: should you receive an error like `Invalid 'tools': array too long. Expected an array with maximum length 128, but got an array with length 132 instead`, you can reduce the number by filtering out tools using the allow/deny patterns documented in this page.

- **Coder MCP tools not being injected**: in order for Coder MCP tools to be injected, the internal MCP server needs to be active. Follow the instructions in the [MCP Server](../mcp-server.md) page to enable it and ensure `CODER_AI_GATEWAY_INJECT_CODER_MCP_TOOLS` is set to `true`.

- **External Auth tools not being injected**: this is generally due to the requesting user not being authenticated against the [External Auth](../../admin/external-auth/index.md) app; when this is the case, no attempt is made to connect to the MCP server.

---

# AI Gateway Proxy

Source: https://coder.com/docs/ai-coder/ai-gateway/ai-gateway-proxy

> [!NOTE]
> AI Gateway Proxy is part of [AI Governance](../../ai-governance.md), which is
> included with a Premium license.

AI Gateway Proxy extends [AI Gateway](../index.md) to support clients that don't allow base URL overrides.
While AI Gateway requires clients to support custom base URLs, many popular AI coding tools lack this capability.

AI Gateway Proxy solves this by acting as an HTTP proxy that intercepts traffic to supported AI providers and forwards it to AI Gateway. Since most clients respect proxy configurations even when they don't support base URL overrides, this provides a universal compatibility layer for AI Gateway.

For a list of clients supported through AI Gateway Proxy, see [Client Configuration](../clients/index.md).

## How it works

AI Gateway Proxy operates in two modes depending on the destination:

* MITM (Man-in-the-Middle) mode for the hostnames of enabled AI providers:
  * Intercepts and decrypts HTTPS traffic using a configured CA certificate
  * Forwards requests to AI Gateway for authentication, auditing, and routing
  * Covers the hostname from each enabled provider's base URL

* Tunnel mode for all other traffic:
  * Passes requests through without decryption

Clients authenticate by passing their Coder token in the proxy credentials.

![AI Gateway Proxy MITM and tunnel modes](../../../images/aibridge/ai-gateway-proxy-modes.png)

## When to use AI Gateway Proxy

Use AI Gateway Proxy when your AI tools don't support base URL overrides but do respect standard proxy configurations.

For clients that support base URL configuration, you can use [AI Gateway](../index.md) directly.
Nevertheless, clients with base URL overrides also work with the proxy, in case you want to use multiple AI clients and some of them do not support base URL configuration.

## Next steps

* [Set up AI Gateway Proxy](./setup.md) on your Coder deployment

---

# Setup

Source: https://coder.com/docs/ai-coder/ai-gateway/ai-gateway-proxy/setup

AI Gateway Proxy runs inside the Coder control plane (`coderd`), requiring no separate compute to deploy or scale.
Once enabled, `coderd` runs the AI Gateway Proxy in-process and intercepts traffic to supported AI providers, forwarding it to AI Gateway.

**Required:**

1. AI Gateway must be enabled and configured (requires a Premium license, which includes [AI Governance](../../ai-governance.md)). See [AI Gateway Setup](../setup.md) for further information.
1. AI Gateway Proxy must be [enabled](#proxy-configuration) using the `coder server` flag.
1. A [CA certificate](#ca-certificate) must be configured for MITM interception.
1. [Clients](#client-configuration) must be configured to use the proxy and trust the CA certificate.

## Proxy Configuration

AI Gateway Proxy is disabled by default. To enable it, set the following configuration options:

```sh
CODER_AI_GATEWAY_ENABLED=true \
CODER_AI_GATEWAY_PROXY_ENABLED=true \
CODER_AI_GATEWAY_PROXY_CERT_FILE=/path/to/ca.crt \
CODER_AI_GATEWAY_PROXY_KEY_FILE=/path/to/ca.key \
coder server
# or via CLI flags:
coder server \
  --ai-gateway-enabled=true \
  --ai-gateway-proxy-enabled=true \
  --ai-gateway-proxy-cert-file=/path/to/ca.crt \
  --ai-gateway-proxy-key-file=/path/to/ca.key
```

Both the certificate and private key are required for AI Gateway Proxy to start.
See [CA Certificate](#ca-certificate) for how to generate and obtain these files.

By default, the proxy listener accepts plain HTTP connections.
To serve the listener over HTTPS, provide a TLS certificate and key:

```sh
CODER_AI_GATEWAY_PROXY_TLS_CERT_FILE=/path/to/listener.crt
CODER_AI_GATEWAY_PROXY_TLS_KEY_FILE=/path/to/listener.key
# or via CLI flags:
--ai-gateway-proxy-tls-cert-file=/path/to/listener.crt
--ai-gateway-proxy-tls-key-file=/path/to/listener.key
```

Both files must be provided together.
The TLS certificate must include a Subject Alternative Name (SAN) matching the hostname or IP address that clients use to connect to the proxy.
See [Proxy TLS Configuration](#proxy-tls-configuration) for how to generate and configure these files.

The proxy intercepts HTTPS traffic for hostnames matching the base URL of each enabled AI [Provider](../providers.md) configured in AI Gateway.
All other traffic is tunneled through without decryption.

### Proxy target

Intercepted requests are forwarded to the AI Gateway, configured via [`CODER_AI_GATEWAY_PROXY_TARGET`](../../../reference/cli/server/index.md#--ai-gateway-proxy-target).
By default, this is the embedded AI Gateway at `<coderd-access-url>/api/v2/ai-gateway`, and no configuration is needed.

AI Gateway Proxy remains part of the `coderd` process when you [deploy AI Gateway as a standalone service](../standalone.md).
To forward intercepted requests to the standalone gateway, set the following:

```sh
CODER_AI_GATEWAY_PROXY_TARGET=https://ai-gateway.example.com/
# or via CLI flag:
--ai-gateway-proxy-target=https://ai-gateway.example.com/
```

The target is used as-is: the proxy appends only the provider and request path to it, and the URL must not include query parameters.

For additional configuration options, see the [`coder server` configuration](../../../reference/cli/server/index.md#options).

## Security Considerations

> [!WARNING]
> The AI Gateway Proxy should only be accessible within a trusted network and **must not** be directly exposed to the public internet.
> Without proper network restrictions, unauthorized users could route traffic through the proxy or intercept credentials.

### Encrypt client connections

By default, AI tools send the Coder session token in the proxy credentials over unencrypted HTTP.
This only applies to the initial connection between the client and the proxy.
Once connected:

* MITM mode: A TLS connection is established between the AI tool and the proxy (using the configured CA certificate), then traffic is forwarded securely to AI Gateway.
* Tunnel mode: A TLS connection is established directly between the AI tool and the destination, passing through the proxy without decryption.

As a best practice, apply one or more of the following to protect credentials during the initial connection:

* TLS listener (recommended): Enable TLS directly on the proxy so clients connect over HTTPS.
See [Proxy TLS Configuration](#proxy-tls-configuration) for configuration steps.
* Internal network only: If the proxy and all clients are on the same trusted network, credentials are not exposed to external attackers.
* TLS-terminating load balancer: Place a TLS-terminating load balancer in front of the proxy that terminates TLS and forwards requests over HTTP.

### Restrict proxy access

Requests to non-allowlisted domains are tunneled through the proxy, but connections to private and reserved IP ranges are blocked by default.
The IP validation and TCP connect happen atomically, preventing DNS rebinding attacks where the resolved address could change between the check and the connection.
To prevent unauthorized use, restrict network access to the proxy so that only authorized clients can connect.

In case the AI Gateway [proxy target](#proxy-target) hostname (the Coder access URL by default) resolves to a private address, it is automatically exempt from this restriction so the proxy can always reach the configured AI Gateway.
If you need to allow access to additional internal networks via the proxy, use the Allowlist CIDRs option ([`CODER_AI_GATEWAY_PROXY_ALLOWED_PRIVATE_CIDRS`](../../../reference/cli/server/index.md#--ai-gateway-proxy-allowed-private-cidrs)):

```sh
CODER_AI_GATEWAY_PROXY_ALLOWED_PRIVATE_CIDRS=10.0.0.0/8,172.16.0.0/12
# or via CLI flag:
--ai-gateway-proxy-allowed-private-cidrs=10.0.0.0/8,172.16.0.0/12
```

## CA Certificate

AI Gateway Proxy uses a CA (Certificate Authority) certificate to perform MITM interception of HTTPS traffic.
When AI tools connect to AI provider domains through the proxy, the proxy presents a certificate signed by this CA.
AI tools must trust this CA certificate, otherwise, the connection will fail.

### Self-signed certificate

Use a self-signed certificate when your organization doesn't have an internal CA, or when you want a dedicated CA specifically for AI Gateway Proxy.

Generate a CA certificate specifically for AI Gateway Proxy:

1) Generate a private key:

```sh
openssl genrsa -out ca.key 4096
chmod 400 ca.key
```

1) Create a self-signed CA certificate (valid for 10&nbsp;years):

```sh
openssl req -new -x509 -days 3650 \
  -key ca.key \
  -out ca.crt \
  -subj "/CN=AI Gateway Proxy CA"
```

Configure AI Gateway Proxy with both files:

```sh
CODER_AI_GATEWAY_PROXY_CERT_FILE=/path/to/ca.crt
CODER_AI_GATEWAY_PROXY_KEY_FILE=/path/to/ca.key
```

### Corporate CA certificate

If your organization has an internal CA that clients already trust, you can have it issue an intermediate CA certificate for AI Gateway Proxy.
This simplifies deployment since AI tools that already trust your organization's root CA will automatically trust certificates signed by the intermediate.

Your organization's CA issues a certificate and private key pair for the proxy. Configure the proxy with both files:

```sh
CODER_AI_GATEWAY_PROXY_CERT_FILE=/path/to/intermediate-ca.crt
CODER_AI_GATEWAY_PROXY_KEY_FILE=/path/to/intermediate-ca.key
```

### Secure the private key

> [!WARNING]
> The CA private key is used to sign certificates for MITM interception.
> Store it securely and restrict access. If compromised, an attacker could intercept traffic from any client that trusts the CA certificate.

Best practices:

* Restrict file permissions so only the Coder process can read the key.
* Use a secrets manager to store the key where possible.

### Distribute the certificate

AI tools need to trust the CA certificate before connecting through the proxy.

For **self-signed certificates**, AI tools must be configured to trust the CA certificate. The certificate (without the private key) is available at:

```sh
https://<coder-url>/api/v2/ai-gateway/proxy/ca-cert.pem
```

For **corporate CA certificates**, if the systems where AI tools run already trust your organization's root CA, and the intermediate certificate chains correctly to that root, no additional certificate distribution is needed.
Otherwise, AI tools must be configured to trust the intermediate CA certificate from the endpoint above.

How you configure AI tools to trust the certificate depends on the tool and operating system. See [Client Configuration](#client-configuration) for details.

## Proxy TLS Configuration

By default, the AI Gateway Proxy listener accepts plain HTTP connections.
When TLS is enabled, the proxy serves over HTTPS, encrypting the connection between AI tools and the proxy.

The TLS certificate is separate from the [MITM CA certificate](#ca-certificate).
The CA certificate is used to sign dynamically generated certificates during MITM interception.
The TLS certificate identifies the proxy itself, like any standard web server certificate.

The AI Gateway Proxy enforces a minimum TLS version of 1.2.

### Configuration

In addition to the required proxy configuration, set the following to enable TLS on the proxy:

```sh
CODER_AI_GATEWAY_PROXY_TLS_CERT_FILE=/path/to/listener.crt
CODER_AI_GATEWAY_PROXY_TLS_KEY_FILE=/path/to/listener.key
# or via CLI flags:
--ai-gateway-proxy-tls-cert-file=/path/to/listener.crt
--ai-gateway-proxy-tls-key-file=/path/to/listener.key
```

Both files must be provided together. If only one is set, the proxy will fail to start.

### Self-signed certificate

Use a self-signed certificate when your organization doesn't have an internal CA, or when you want a dedicated certificate specifically for the AI Gateway Proxy.

The TLS certificate must include a Subject Alternative Name (SAN) matching the hostname or IP address that clients use to connect to the proxy.
Without a matching SAN, clients will reject the connection.

1) Generate a private key:

```sh
openssl genrsa -out listener.key 4096
chmod 400 listener.key
```

1) Create a self-signed certificate:

```sh
openssl req -new -x509 -days 365 \
  -key listener.key \
  -out listener.crt \
  -subj "/CN=<proxy-host>" \
  -addext "subjectAltName=DNS:<proxy-host>,IP:<proxy-ip>"
```

Replace `<proxy-host>` and `<proxy-ip>` with the hostname and IP address that clients use to connect to the proxy.

### Corporate CA certificate

If your organization has an internal CA, have it issue a leaf certificate for the proxy.
The certificate must include a SAN matching the proxy's hostname or IP address.

If clients already trust your organization's root CA, no additional certificate configuration is needed for the TLS connection to the proxy.

### Trust the TLS certificate

For **self-signed certificates**, AI tools must be configured to trust the TLS certificate.

For **corporate CA certificates**, if the systems where AI tools run already trust your organization's root CA, no additional configuration is needed.

How you configure AI tools to trust the certificate depends on the tool and operating system.
See [Client Configuration](#client-configuration) for details.

## Upstream proxy

If your organization requires all outbound traffic to pass through a corporate proxy, you can configure AI Gateway Proxy to chain requests to an upstream proxy.

> [!NOTE]
> AI Gateway Proxy must be the first proxy in the chain.
> AI tools must be configured to connect directly to AI Gateway Proxy, which then forwards tunneled traffic to the upstream proxy.

### How it works

Tunneled requests (non-allowlisted domains) are forwarded to the upstream proxy configured via [`CODER_AI_GATEWAY_PROXY_UPSTREAM`](../../../reference/cli/server/index.md#--ai-gateway-proxy-upstream).

MITM'd requests (AI provider domains) are forwarded to AI Gateway, which then communicates with AI providers.
To ensure AI Gateway also routes requests through the upstream proxy, make sure to configure the proxy settings for the `coderd` process.

![AI Gateway Proxy with an upstream corporate proxy](../../../images/aibridge/ai-gateway-proxy-upstream.png)

> [!NOTE]
> When an upstream proxy is configured, AI Gateway Proxy validates the destination IP before forwarding the request.
> However, the upstream proxy re-resolves DNS independently, so a small DNS rebinding window exists between the validation and the actual connection.
> Ensure your upstream proxy enforces its own restrictions on private and reserved IP ranges.

### Configuration

Configure the upstream proxy URL:

```sh
CODER_AI_GATEWAY_PROXY_UPSTREAM=http://<corporate-proxy-url>:8080
```

For HTTPS upstream proxies, if the upstream proxy uses a certificate not trusted by the system, provide the CA certificate:

```sh
CODER_AI_GATEWAY_PROXY_UPSTREAM=https://<corporate-proxy-url>:8080
CODER_AI_GATEWAY_PROXY_UPSTREAM_CA=/path/to/corporate-ca.crt
```

If the system already trusts the upstream proxy's CA certificate, [`CODER_AI_GATEWAY_PROXY_UPSTREAM_CA`](../../../reference/cli/server/index.md#--ai-gateway-proxy-upstream-ca) is not required.

## Client Configuration

To use AI Gateway Proxy, AI tools must be configured to:

1. Route traffic through the proxy
1. Trust the proxy's CA certificate

### Configure the proxy

The preferred approach is to configure the proxy directly in the AI tool's settings, as this avoids routing unnecessary traffic through the proxy.
Consult the tool's documentation for specific instructions.

Alternatively, most tools support the standard `HTTPS_PROXY` environment variable, though this is not guaranteed for all tools:

```sh
export HTTPS_PROXY="https://coder:${CODER_SESSION_TOKEN}@<proxy-host>:8888"
```

Note: if [TLS is not enabled](#proxy-tls-configuration) on the proxy, replace `https://` with `http://` in the proxy URL.

`HTTPS_PROXY` is used for requests to `https://` URLs, which includes all supported AI provider domains.

> [!NOTE]
> `HTTP_PROXY` is not required since AI providers only use `HTTPS`.
> Leaving it unset avoids routing unnecessary traffic through the proxy.

In order for AI tools that communicate with AI Gateway Proxy to authenticate with Coder via AI Gateway, the Coder session token needs to be passed in the proxy credentials as the password field.

### Trust the CA certificate

The preferred approach is to configure the CA certificate directly in the AI tool's settings, as this limits the scope of the trusted certificate to that specific application.
Consult the tool's documentation for specific instructions.

> [!NOTE]
> If using a [corporate CA certificate](#corporate-ca-certificate) and the system already trusts your organization's root CA, no additional certificate configuration is required.

Download the certificate:

```sh
curl -o coder-ai-gateway-proxy-ca.pem \
  -H "Coder-Session-Token: ${CODER_SESSION_TOKEN}" \
  https://<coder-url>/api/v2/ai-gateway/proxy/ca-cert.pem
```

Replace `<coder-url>` with your Coder deployment URL.

When [TLS is enabled](#proxy-tls-configuration) on the proxy, AI tools must trust both the [MITM CA certificate](#ca-certificate) and the [TLS certificate](#proxy-tls-configuration).
Combine both certificates into a single PEM file:

```sh
cat coder-ai-gateway-proxy-ca.pem listener.crt > combined-ca.pem
```

Use this combined file for any of the environment variables listed below.

#### Environment variables

Different AI tools use different runtimes, each with their own environment variable for CA certificates:

| Environment Variable  | Runtime                   |
|-----------------------|---------------------------|
| `NODE_EXTRA_CA_CERTS` | Node.js                   |
| `SSL_CERT_FILE`       | OpenSSL, Python, curl     |
| `REQUESTS_CA_BUNDLE`  | Python `requests` library |
| `CURL_CA_BUNDLE`      | curl                      |

Set the environment variables associated with the AI tool's runtime.
If you're unsure which runtime the tool uses, or if you use multiple AI tools, the simplest approach is to set all of them:

```sh
export NODE_EXTRA_CA_CERTS="/path/to/coder-ai-gateway-proxy-ca.pem"
export SSL_CERT_FILE="/path/to/coder-ai-gateway-proxy-ca.pem"
export REQUESTS_CA_BUNDLE="/path/to/coder-ai-gateway-proxy-ca.pem"
export CURL_CA_BUNDLE="/path/to/coder-ai-gateway-proxy-ca.pem"
```

#### System trust store

When tool-specific or environment variable configuration is not possible, you can add the certificate to the system trust store.
This makes the certificate trusted by all applications on the system.

On Linux:

```sh
sudo cp coder-ai-gateway-proxy-ca.pem /usr/local/share/ca-certificates/
sudo update-ca-certificates
```

For other operating systems, refer to the system's documentation for instructions on adding trusted certificates.

### Coder workspaces

For AI tools running inside Coder workspaces, template administrators can pre-configure the proxy settings and CA certificate in the workspace template.
This provides a seamless experience where users don't need to configure anything manually.

The [AI Gateway Proxy module](https://registry.coder.com/modules/coder/aibridge-proxy) helps with proxy setup.
It downloads the proxy's CA certificate into the workspace and exposes Terraform outputs.
The module does not set proxy environment variables globally on the workspace.

> [!NOTE]
> The module source path retains the former `aibridge-proxy` name even though the feature is now called AI Gateway Proxy.

For tool-specific configuration details, check the [client compatibility table](../clients/index.md#compatibility) for clients that require proxy-based integration.

## Troubleshooting

### TLS certificate verification failures

TLS verification can fail on either leg of the connection: between AI Gateway Proxy and Coder, or between the AI tool and the proxy.

#### AI Gateway Proxy to Coder

When the AI Gateway [proxy target](#proxy-target) URL (the Coder access URL by default) uses HTTPS, AI Gateway Proxy must trust the TLS certificate served at that URL (either Coder's
own certificate or a load balancer's, if TLS is terminated there) to forward intercepted requests to AI Gateway.
This primarily affects deployments using a self-signed or internal CA, since publicly trusted CAs are typically already
in the system trust store.
If the certificate is signed by a CA not in the system trust store, the connection fails and `coderd` logs:

```sh
WARN: Cannot read TLS response from mitm'd server tls: failed to verify certificate: x509: certificate signed by unknown authority
```

To resolve, add the CA that signed that certificate to the [system trust store](#system-trust-store) of the host running
AI Gateway Proxy (the same host as `coderd`, since the proxy runs in-process), then restart Coder so AI Gateway Proxy
reloads the trust store.

#### Client to AI Gateway Proxy

If an AI tool fails with:

```sh
x509: certificate signed by unknown authority
```

it has not been configured to trust the proxy's
MITM CA certificate. Visit [Trust the CA certificate](#trust-the-ca-certificate). If
[TLS is enabled on the listener](#proxy-tls-configuration), the tool must trust that certificate as well.

### Requests are not being intercepted

The proxy intercepts HTTPS traffic only for hostnames matching the base URL of an enabled AI [Provider](../providers.md) configured in AI
Gateway. Check that the provider is enabled and its base URL matches the hostname the tool is connecting to. Verify that
`HTTPS_PROXY` points at the proxy. When interception is working, `coderd` logs:

```sh
routing MITM request to AI Gateway
```

for each intercepted request.

### Authentication failures

The Coder token must be supplied as the password in the proxy credentials, for example
`https://coder:${CODER_SESSION_TOKEN}@<proxy-host>:8888`. When a CONNECT request has no usable token, the proxy replies
with `407 Proxy Authentication Required` and logs:

```sh
WARN  rejecting CONNECT request  host=... provider=... reason=missing_credentials
```

`reason=missing_credentials` means no `Proxy-Authorization` header was sent. `reason=invalid_credentials` means a header
was sent but no token could be read from the password field.

A `401 Unauthorized` from AI Gateway means the token was
rejected as expired or invalid.

> [!NOTE]
> Some clients may send the first request without credentials and retry on a `407` response.
> An initial `missing_credentials` warning can accompany a connection that ultimately succeeds.

Confirm the token is current and set in the password field of the proxy credentials.
See [Client Configuration](#client-configuration) for how to configure the proxy credentials.

### Connections to internal services are blocked

Tunneled requests to private or reserved IP ranges are blocked by default. When a request is blocked, `coderd` logs:

```sh
WARN  blocking connection to private/reserved IP  hostname=... port=... resolved_ip=...
```

To allow specific internal networks, set
[`CODER_AI_GATEWAY_PROXY_ALLOWED_PRIVATE_CIDRS`](#restrict-proxy-access).

---

# Provider Configuration

Source: https://coder.com/docs/ai-coder/ai-gateway/providers

> [!NOTE]
> AI Gateway is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

Providers are deployment-scoped and managed from the dashboard or the
[AI Providers API](../../reference/api/aiproviders.md). See
[Setup](./setup.md#configure-providers) for the steps to add, edit, and
disable a provider.

This page covers the provider types AI Gateway supports, the setup
considerations for each, how a provider's lifecycle affects request
handling, and how to monitor providers.

## Database management of providers

Manage provider records through the dashboard at `https://<your-coder-host>/ai/settings/providers` or [AI Providers API](../../reference/api/aiproviders.md).

Provider setup through environment variables, CLI flags, and YAML is no longer supported.
Leftover provider environment variables are ignored and no longer seed the database.

> [!WARNING]
> A removed provider CLI flag or YAML key prevents Coder from starting, with an `unknown flag` or `unknown option` error.
> Files generated by `coder server --write-config` in older versions include these YAML keys by default, even if you never configured an AI provider.

<details>
<summary>Provider options to remove before upgrading</summary>

Remove any of the following options from your deployment configuration, including empty or default-valued YAML entries.
The table shows AI Gateway names.
For AI Bridge aliases, replace `CODER_AI_GATEWAY_` with `CODER_AIBRIDGE_`, `--ai-gateway-` with `--aibridge-`, and the YAML group `ai_gateway` with `aibridge`.

| Option                    | Environment variable                         | CLI flag                                 | YAML key under `ai_gateway` |
|---------------------------|----------------------------------------------|------------------------------------------|-----------------------------|
| Indexed providers         | `CODER_AI_GATEWAY_PROVIDER_<N>_*`            | None                                     | None                        |
| OpenAI base URL           | `CODER_AI_GATEWAY_OPENAI_BASE_URL`           | `--ai-gateway-openai-base-url`           | `openai_base_url`           |
| OpenAI API key            | `CODER_AI_GATEWAY_OPENAI_KEY`                | `--ai-gateway-openai-key`                | None                        |
| Anthropic base URL        | `CODER_AI_GATEWAY_ANTHROPIC_BASE_URL`        | `--ai-gateway-anthropic-base-url`        | `anthropic_base_url`        |
| Anthropic API key         | `CODER_AI_GATEWAY_ANTHROPIC_KEY`             | `--ai-gateway-anthropic-key`             | None                        |
| Bedrock base URL          | `CODER_AI_GATEWAY_BEDROCK_BASE_URL`          | `--ai-gateway-bedrock-base-url`          | `bedrock_base_url`          |
| Bedrock region            | `CODER_AI_GATEWAY_BEDROCK_REGION`            | `--ai-gateway-bedrock-region`            | `bedrock_region`            |
| Bedrock access key        | `CODER_AI_GATEWAY_BEDROCK_ACCESS_KEY`        | `--ai-gateway-bedrock-access-key`        | None                        |
| Bedrock secret access key | `CODER_AI_GATEWAY_BEDROCK_ACCESS_KEY_SECRET` | `--ai-gateway-bedrock-access-key-secret` | None                        |
| Bedrock model             | `CODER_AI_GATEWAY_BEDROCK_MODEL`             | `--ai-gateway-bedrock-model`             | `bedrock_model`             |
| Bedrock small fast model  | `CODER_AI_GATEWAY_BEDROCK_SMALL_FAST_MODEL`  | `--ai-gateway-bedrock-small-fastmodel`   | `bedrock_small_fast_model`  |

Credential options had no YAML equivalent, and indexed provider options were environment-only.

</details>

Providers already stored in the database remain available without these options.

Both the embedded gateway and a [standalone gateway](./standalone.md) fetch provider configuration from Coder.

## Provider types

AI Gateway speaks two upstream API formats: the **OpenAI** format
(Chat Completions and Responses) and the **Anthropic** format
(Messages). Every provider type maps to one of these.

| Type            | API format | Setup notes                                                       |
|-----------------|------------|-------------------------------------------------------------------|
| `openai`        | OpenAI     | Native OpenAI, or any OpenAI-compatible endpoint via the base URL |
| `anthropic`     | Anthropic  | Native Anthropic, or an Anthropic-compatible broker               |
| `bedrock`       | Anthropic  | Anthropic models hosted on AWS Bedrock; authenticates via AWS     |
| `copilot`       | OpenAI     | GitHub Copilot; authenticates via each user's GitHub OAuth token  |
| `azure`         | OpenAI     | OpenAI-compatible endpoint only                                   |
| `google`        | OpenAI     | OpenAI-compatible endpoint only                                   |
| `openrouter`    | OpenAI     | OpenAI-compatible endpoint only                                   |
| `vercel`        | OpenAI     | OpenAI-compatible endpoint only                                   |
| `openai-compat` | OpenAI     | Generic OpenAI-compatible endpoint                                |

`azure`, `google`, `openrouter`, `vercel`, and `openai-compat` are
supported only as OpenAI-compatible endpoints: AI Gateway sends them
OpenAI-format requests, so each must expose an OpenAI-compatible API at
its base URL. They have no provider-specific integration beyond that.

### OpenAI

Set the base URL to the upstream endpoint and provide an API key. The
default `https://api.openai.com/v1/` targets the native OpenAI service;
point it at any OpenAI-compatible endpoint (for example, a hosted proxy
or LiteLLM deployment) when needed.

If you create an [OpenAI key](https://platform.openai.com/api-keys)
with minimal privileges, this is the minimum required set:

![List Models scope should be set to "Read", Model Capabilities set to "Request"](../../images/aibridge/openai_key_scope.png)

### Anthropic

Set the base URL and provide an API key. The default
`https://api.anthropic.com/` targets Anthropic's public API; override it
for Anthropic-compatible brokers.

Anthropic does not allow [API keys](https://console.anthropic.com/settings/keys)
to have restricted permissions at the time of writing (June 2026).

#### Claude Platform for AWS

Claude Platform for AWS is Anthropic's own Messages API hosted on AWS. It
is an authentication method on the `anthropic` provider type, not a
separate provider type: requests and responses are the standard Anthropic
format with standard Anthropic model IDs, and only routing and
authentication differ. It is distinct from
[Amazon Bedrock](#amazon-bedrock), which is a separate provider type.

Every Claude Platform provider requires:

- A **region**, for example `us-east-1`. It selects the default endpoint
  `https://aws-external-anthropic.<region>.api.aws` and, for IAM
  authentication, the signing scope. Set it explicitly even when you
  override the endpoint, so requests routed through a proxy are still
  signed for the correct region.
- A **workspace ID**, sent as the `anthropic-workspace-id` header on
  every request. AI Gateway sets the header from provider configuration
  and strips any value a client sends, so a client cannot choose which
  workspace its traffic is attributed to.

AI Gateway chooses authentication from the credentials available for each request:

1. When [Bring Your Own Key](#bring-your-own-key) is enabled, a client key takes precedence over stored provider keys and IAM signing.
2. Otherwise, AI Gateway uses the provider's stored API-key collection, with key pooling, rotation, masking, and [key failover](#key-failover).
3. When no client or stored provider key is available, AI Gateway signs the request with AWS SigV4 for the `aws-external-anthropic` service using its ambient AWS credentials.

Configure the AWS identity on the gateway process through the default AWS credential chain, such as an instance profile, container identity, or `AWS_PROFILE`.
Individual Claude Platform provider settings do not select an AWS identity or authentication mode.
Adding a stored key selects API-key authentication; removing the last stored key allows requests without a client key to use IAM.

A supplied key that fails authentication does not trigger a fallback to IAM.
A client sending an ordinary Anthropic key to a Claude Platform provider receives an upstream authentication error.

### Amazon Bedrock

Bedrock providers serve Anthropic models hosted on AWS and authenticate
with AWS credentials rather than a registered API key. Configure:

- A **protocol**, either `InvokeModel` or `Mantle`. It determines the
  endpoint format and which of the fields below apply. See
  [InvokeModel](#invokemodel) and [Mantle](#mantle).
- An **endpoint** in the format the protocol requires:
  `https://bedrock-runtime.<region>.amazonaws.com` for InvokeModel or
  `https://bedrock-mantle.<region>.api.aws/anthropic` for Mantle. The AWS
  region is read from the endpoint host.
- The **model** and **small fast model** identifiers, for InvokeModel
  only. Mantle providers do not set them; the client chooses the model on
  each request and AI Gateway forwards it upstream.

#### InvokeModel

The legacy Bedrock runtime API. AI Gateway translates each request into
Bedrock's InvokeModel format and sends it to
`https://bedrock-runtime.<region>.amazonaws.com`. Still supported, but
Mantle is recommended for new deployments.

#### Mantle

The newer Anthropic-compatible Bedrock endpoint, recommended by AWS for new
deployments. AI Gateway serves Anthropic models through the native Messages
API, forwarding the request body **unchanged** and only applying AWS SigV4
signing with the provider's base identity.

To route Claude Code through a Mantle provider, run it in mantle mode with
client-side signing disabled so the gateway signs centrally:

```sh
export CLAUDE_CODE_USE_MANTLE=1
export CLAUDE_CODE_SKIP_MANTLE_AUTH=1
export ANTHROPIC_BEDROCK_MANTLE_BASE_URL="${CODER_URL}/api/v2/ai-gateway/${PROVIDER_NAME}"
export ANTHROPIC_AUTH_TOKEN="${CODER_TOKEN}"
```

You can also validate that the provider works with `curl`:

```sh
curl "${CODER_URL}/api/v2/ai-gateway/${PROVIDER_NAME}/v1/messages" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${CODER_TOKEN}" \
  -H "Anthropic-Version: 2023-06-01" \
  -d '{"model": "anthropic.claude-sonnet-5","max_tokens": 1024,"messages": [{"role": "user", "content": "Hello, Claude"}]}'
```

#### AWS credentials

Do not attach API keys to a Bedrock provider. The provider itself always
authenticates with AWS credentials.

When [BYOK](auth.md#bring-your-own-key-byok) is enabled, a user can save a
personal Amazon Bedrock API key under their
[Agents API keys](../agents/models.md#user-api-keys-byok). AI Gateway then
sends that key as a bearer token for the user's requests instead of signing
them with the deployment's AWS credentials. Requests from users without a
personal key continue to use the credentials below.

AI Gateway resolves AWS credentials one of three ways:

- **AWS SDK default credential chain (recommended).** When no explicit
  credentials are configured, the AWS SDK resolves them automatically
  from the environment: IAM Roles (instance profiles, IRSA, ECS task
  roles), shared config files, environment variables, SSO, and more.
  Attaching an IAM Role to the compute running Coder follows
  [AWS best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html)
  for temporary credentials. The role must permit `bedrock:InvokeModel`
  and `bedrock:InvokeModelWithResponseStream` for the configured models.
- **Static credentials.** Provide an access key and secret for an IAM
  user with the same Bedrock permissions.
- **Assumed IAM role.** Set a **Role ARN** to have the gateway assume
  that role before calling Bedrock, signing requests with the resulting
  temporary credentials. This works on top of either of the above base
  identities and supports cross-account Bedrock access. See
  [IAM role assumption](#iam-role-assumption).

#### Static Bedrock credentials

When you cannot use the default credential chain, create a dedicated IAM
user and generate a static access key:

1. **Choose a region** where you want to use Bedrock.

2. **Generate API keys** in the [AWS Bedrock console](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/api-keys/long-term/create) (replace `us-east-1` in the URL with your chosen region):
   - Choose an expiry period for the key.
   - Select **Generate**.
   - This creates an IAM user with strictly-scoped permissions for Bedrock access.

3. **Create an access key** for the IAM user:
   - After generating the API key, select **"You can directly modify permissions for the IAM user associated"**.
   - In the IAM user page, navigate to the **Security credentials** tab.
   - Under **Access keys**, select **Create access key**.
   - Select **"Application running outside AWS"** as the use case.
   - Select **Next**.
   - Add a description like "Coder AI Gateway token".
   - Select **Create access key**.
   - Save both the access key ID and secret access key securely.

4. **Enter the access key ID and secret access key** when you add or edit
   the Bedrock provider from the dashboard or the
   [AI Providers API](../../reference/api/aiproviders.md), along with the
   region (or base URL) and model identifiers.

#### IAM role assumption

Set the optional **Role ARN** field to have the gateway assume an IAM
role before calling Bedrock. The base identity (static credentials or the
default credential chain) signs an STS `AssumeRole` call, and the
temporary credentials it returns sign Bedrock requests. The field is
optional: a provider with no Role ARN authenticates with its base
identity directly, exactly as described above.

To use role assumption:

1. **Create the IAM role** in the target account and grant it
   `bedrock:InvokeModel` and `bedrock:InvokeModelWithResponseStream` for
   the configured models. The base identity does not need Bedrock
   permissions itself; the assumed role does.

2. **Configure the role's trust policy** to allow the gateway's base
   identity to assume it.

3. **Enter the Role ARN** when you add or edit the Bedrock provider. It must be a
   valid IAM role ARN, for example `arn:aws:iam::123456789012:role/BedrockRole`.

Each provider assumes a single role. To use several roles, configure one
provider per role.

#### External ID

When a Bedrock provider assumes a role, the gateway generates a unique
**external ID** for it and sends that value on every `AssumeRole` call.
The external ID guards against the
[confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html)
on cross-account assumption. The gateway generates and owns the value, as
AWS [recommends](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html):
you cannot set or change it. It is not a secret, and it is shown on the
provider's edit page once a Role ARN is configured.

To enforce it, add the external ID to the target role's trust policy as an
`sts:ExternalId` condition:

```json
{
  "Effect": "Allow",
  "Principal": { "AWS": "<gateway base identity>" },
  "Action": "sts:AssumeRole",
  "Condition": { "StringEquals": { "sts:ExternalId": "<the provider's External ID>" } }
}
```

> [!IMPORTANT]
> The gateway sends the external ID whether or not the trust policy checks
> it. Until you add the `sts:ExternalId` condition, the value is sent but
> not enforced, and the role can still be assumed without it. To rotate the
> external ID, recreate the provider.

#### Application inference profiles

For InvokeModel, the **model** and **small fast model** identifiers can be
[application inference profile](https://docs.aws.amazon.com/bedrock/latest/userguide/cost-mgmt-application-inference-profiles.html)
ARNs, which attribute Bedrock spend to a team or workload through AWS cost
allocation tags.

AI Gateway passes the profile upstream so AWS records the attribution, while
internally resolving and using the underlying model identity, including for
usage pricing.

Resolution requires a `GetInferenceProfile` call, so the AWS identity used by
the gateway must have `bedrock:GetInferenceProfile` permission for the
profile. Providers configured with plain model identifiers do not need this
permission. If resolution fails, the provider is skipped.

### GitHub Copilot

GitHub Copilot offers three plans: Individual, Business, and Enterprise,
each with its own API endpoint. Add one `copilot` provider per plan your
organization uses, setting the base URL accordingly:

| Plan       | Base URL                                   |
|------------|--------------------------------------------|
| Individual | `https://api.individual.githubcopilot.com` |
| Business   | `https://api.business.githubcopilot.com`   |
| Enterprise | `https://api.enterprise.githubcopilot.com` |

Copilot providers authenticate with each user's request-time GitHub
OAuth token, so do not attach API keys. For client-side setup (proxy,
certificates, IDE configuration), see
[GitHub Copilot client configuration](./clients/copilot.md).

### ChatGPT

ChatGPT subscriptions (Plus, Pro, Business) are supported through a
provider of type `openai` with a specific name and base URL:

| Field    | Value                                   |
|----------|-----------------------------------------|
| Type     | `openai`                                |
| Name     | `chatgpt`                               |
| Base URL | `https://chatgpt.com/backend-api/codex` |

The name must be exactly `chatgpt`. It determines the route clients use
to reach the provider: `/api/v2/ai-gateway/chatgpt/v1`. If no provider
with this name exists, requests to that route fail with
`404 route not supported`.

Do not attach API keys. ChatGPT providers authenticate with each user's
ChatGPT OAuth token through [BYOK](./auth.md#bring-your-own-key-byok),
so BYOK must remain enabled. For client-side setup, see the
[Codex CLI ChatGPT subscription configuration](./clients/codex.md#byok-chatgpt-subscription).

### OpenAI-compatible providers

Azure-hosted OpenAI, Google, OpenRouter, Vercel, and any other
OpenAI-compatible service are configured with the matching type (or the
generic `openai-compat`), the provider's OpenAI-compatible base URL, and
an API key.

> [!NOTE]
> See the [Supported APIs](./reference.md#supported-apis) section for
> precise endpoint coverage and interception behavior.

## Provider lifecycle

Every provider carries an explicit status, reported by the [`provider_info`](./monitoring.md#prometheus-metrics) metrics.
`coder_ai_gateway_provider_info` reports `enabled`, `disabled`, and `error`, and `coder_ai_gateway_proxy_provider_info` also reports `proxy_excluded`:

| Status           | Meaning                                                                                                                                                             | Effect on requests                                                                                                             |
|------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
| `enabled`        | Configuration is valid and the provider is serving traffic                                                                                                          | Requests are proxied to the upstream                                                                                           |
| `disabled`       | The provider exists but has been turned off                                                                                                                         | Requests are rejected with a non-retryable error                                                                               |
| `error`          | The provider is enabled but cannot be built (missing credentials, bad config)                                                                                       | Requests fail; the error is surfaced in metrics                                                                                |
| `proxy_excluded` | Another enabled provider already claims this hostname; the AI Gateway Proxy routes traffic to the first claimant (by database name sort order, `ORDER BY name ASC`) | Proxy-routed requests go to the first claimant; direct routing (`/api/v2/ai-gateway/{name}/...`) still works for this provider |

Disabling a provider does not delete it, its credentials, or its
historical interception data. Re-enabling restores it to service.

## Monitoring and reloads

Provider configuration changes take effect automatically, without
restarting `coderd`. AI Gateway records the timestamp of each reload
attempt and each successful reload, exposed as Prometheus metrics:

- `coder_ai_gateway_providers_last_reload_timestamp_seconds`
- `coder_ai_gateway_providers_last_reload_success_timestamp_seconds`

If you run the [external proxy](./ai-gateway-proxy/index.md), it exposes
the same pair under the `coder_ai_gateway_proxy_` prefix.
Each [standalone gateway](./standalone.md) replica reloads providers independently and replaces only its own provider snapshot.
If a reload fails, that replica retains its previous provider snapshot and continues serving from it.

A growing gap between the attempt and success timestamps means reloads are firing but failing to apply.
Alert on that gap rather than on a single failure, which may resolve on the next change.
Refer to [Monitoring](./monitoring.md#prometheus-metrics) for the full metric list and sample alert queries.

## Key failover

You can configure multiple centralized API keys for a single provider instance
so that AI Gateway automatically retries with the next key when one fails. This
is transparent to end users, and clients see no difference in behavior or need
any configuration changes.

Key failover is supported for **OpenAI** and **Anthropic** providers. Amazon
Bedrock and GitHub Copilot do not support key failover.

Multiple keys can be added per provider through the
[AI Providers API](../../reference/api/aiproviders.md). Each provider supports
a maximum of **5 keys**.

### Failover behavior

Every request starts with the first key in the list. If a key is rate-limited
(`429 Too Many Requests`) or fails authentication (`401 Unauthorized`), AI
Gateway puts that key on a temporary cooldown and retries the request with the
next available key. Keys recover automatically when the cooldown elapses, so
failover stays transparent to end users. Any other response, including a
`403 Forbidden`, is returned to the caller unchanged.

If all keys in the pool are exhausted, AI Gateway returns:

- `429 Too Many Requests` when at least one key is rate-limited, with a `Retry-After`
header set to the shortest cooldown across all keys.
- `502 Bad Gateway` when every key is in an authentication-failure cooldown.
The keys still recover automatically once their cooldowns elapse, so no `Retry-After` is sent.

## Bring Your Own Key

A provider's configured credentials are the centralized default. When
Bring Your Own Key (BYOK) is enabled, a user's own credential takes
precedence over the provider's for that user's requests, and AI Gateway
falls back to the provider credentials when the user has none. See
[Authentication](./auth.md#bring-your-own-key-byok) for the BYOK flow
and how to enable or disable it.

## Failure modes

| Symptom                                       | Likely cause                                    | Corrective action                     |
|-----------------------------------------------|-------------------------------------------------|---------------------------------------|
| Provider returns errors with no upstream call | The provider is `disabled` or in `error` status | Consult the `coderd` logs for details |
| Configuration changes not taking effect       | Reloads are firing but failing to apply         | Consult the `coderd` logs for details |

---

# Audit AI sessions

Source: https://coder.com/docs/ai-coder/ai-gateway/audit

> [!NOTE]
> AI Gateway is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

AI Gateway groups intercepted requests into **sessions** and **threads** to show
the causal relationships between human prompts and agent actions. This
structure gives auditors clear provenance over who initiated what, and why.

## Concepts

| Term             | Definition                                                                                                                                                                                                                                            |
|------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Interception** | A single intercepted request/response pair between client and provider.                                                                                                                                                |                                                                               |
| **Thread**       | A multi-part interaction starting with a human prompt that triggers one or more tool calls, forming an agentic loop.                                                                                                                                  |
| **Agentic loop** | A sequence of tool invocations the agent performs to satisfy a request. The model ends its turn with a tool call, the client invokes it, sends the result back, and the cycle repeats until the model has enough information to formulate a response. |
| **Session**      | A set of threads grouped by a client-provided session key. Claude Code and Codex provide session IDs automatically; other clients may not.                                                                                                            |

## Human vs. Agent attribution

AI Gateway distinguishes between human-initiated and agent-initiated requests
using the `role` property:

- A message with `role="user"` indicates a human-initiated action (i.e. prompt).
- A message with `role="assistant"` indicates a message generated by a model.
- A message with `role="system"` indicates the system prompt for the client.

The `user` role is currently overloaded by clients like Claude Code and Codex;
they inject system instructions
within `role="user"` blocks when using agents. AI Gateway applies a heuristic
of storing only the **last** prompt from a block of `role="user"` messages.

> [!NOTE]
> AI Gateway cannot declare with certainty whether a request was human- or
> agent-initiated.

## LLM reasoning capture

AI Gateway captures model reasoning and thinking content when available. Both
Anthropic (extended thinking) and OpenAI (reasoning summaries) support this
feature. Reasoning data gives auditors insight into **why** a tool was called,
not just what was called.

<a id="navigating-the-ui"></a>

## Navigate the UI

### Sessions list

The sessions page (`http://<deployment-url>/ai-gateway/sessions`) lists sessions in reverse-chronological order.
By default it shows sessions with activity in the last 24&nbsp;hours.
Use the time range filter in the filter bar to widen or narrow the window, for example to see older sessions.

Each row shows the last prompt, initiator, provider, client, token usage,
network requests, thread count, and timestamp.

The **Network Requests** column reports the total and blocked
[Agent Firewall](../agent-firewall/index.md) requests for the session. It shows
`No activity` when the session made no requests, and `Disabled` when the session
did not pass through Agent Firewall, so no network requests were monitored.

Select one to view its full details.

![Sessions](../../images/aibridge/sessions.png)

### Session detail

Open a session to see a chronological causal chain of events.

A search input next to the Back button filters the events by prompt text,
tool names, tool inputs, and network call destinations. While a query is
active, the timeline shows only matching events and a count below the input
reports how many events match. Matches render in bold in prompts, tool names,
and network call destinations, and a matching prompt expands to show the
match. A "No events match your search in the loaded events." message appears
when nothing in the loaded events matches.

Within a thread, each step shows token usage, tool call details (including
arguments and MCP server URLs), duration, and any errors or warnings.

The **Session summary** card beside the timeline reports the session's
[Agent Firewall](../agent-firewall/index.md) activity:

- **Network requests** is the total number of requests the session made. It
  shows `Disabled` when the session did not pass through Agent Firewall, so
  monitoring was not active, and `No activity` when the session made no
  requests.
- **Blocked network requests** is the subset of those requests that the
  allow-list denied. This row appears only when the session made at least one
  request, and is highlighted when any were blocked.
- **Top domains** names the destination host the session contacted most, and
  appears whenever at least one domain was recorded. When the session contacted
  more than one distinct domain, a `+N more` count follows.

![Session detail](../../images/aibridge/session_detail.png)

<a id="conducting-a-forensic-audit"></a>

## Conduct a forensic audit

When investigating an incident (policy violation, destructive action, etc.):

1. **Identify the session.** Filter by user, time range, or client to find the
   relevant session.
1. **Locate the thread.** Each thread in a session shows the (likely) human prompt
   that initiated the chain of actions.
1. **Trace the causal chain.** Expand the thread to see every step in the
   agentic loop — each tool call and its arguments.
1. **Review model reasoning.** If extended thinking was enabled, check the
   model's reasoning at each step to understand why specific tools were called.
1. **Assess attribution.** The session identifies the human who
   initiated the action. Subsequent interceptions represent agent-driven actions
   that stem from that original prompt.

## What we store

AI Gateway captures the following data from each request/response:

- Last user prompt
- Token usage
- Tool calls (requests only, not responses)
  - Responses may be very large, and generally have lower audit value than requests
  - In future, we will support storing these results
- Model thinking/reasoning

Model-produced inference text is discarded, as generated text alone
cannot affect external systems. The retention philosophy prioritizes:

- **Human prompts** — capture intent and detect policy violations or
  exfiltration attempts.
- **Tool calls** — record how agents interact with external systems,
  which is critical for understanding how incidents occurred. For
  example, an agent might delete and recreate a database because it
  lacks permissions to satisfy a human request to query a table.
- **Model reasoning** — preserve thinking content that explains why
  specific tools were invoked, distinguishing between human instruction
  and model misunderstanding as the root cause.

See [data retention](./setup.md#data-retention) to configure how long
session data is kept.

## Next steps

- [Monitoring](./monitoring.md) — Dashboards, data export, and tracing
- [Setup](./setup.md) — Configure AI Gateway and data retention
- [Reference](./reference.md) — API and technical reference

---

# Monitoring

Source: https://coder.com/docs/ai-coder/ai-gateway/monitoring

> [!NOTE]
> AI Gateway is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

AI Gateway records the last `user` prompt, token usage, model reasoning, and every tool invocation for each intercepted request. Each capture is tied to a single "interception" that maps back to the authenticated Coder identity, making it easy to attribute spend and behaviour.

![User Prompt logging](../../images/aibridge/grafana_user_prompts_logging.png)

![User Leaderboard](../../images/aibridge/grafana_user_leaderboard.png)

We provide an example Grafana dashboard that you can import as a starting point for your metrics.
Refer to the [Grafana dashboard README](../../../examples/monitoring/dashboards/grafana/aibridge/README.md).

These logs and metrics can be used to determine usage patterns, track costs, and evaluate tooling adoption.

## Prometheus metrics

The embedded gateway and [standalone gateway](./standalone.md) export the same AI Gateway request metrics.
Each process exports metrics for the traffic that it handles:

- The Coder control plane (`coderd`) Prometheus listener exports metrics for the embedded gateway.
- Each standalone gateway replica exports metrics from its own Prometheus listener.

Refer to [provider configuration](./providers.md) for the provider reload lifecycle these metrics describe.

The `provider` label is the provider instance name.
Some metrics use the explicit `provider_name` or `provider_type` labels for clarity.

| Metric                                                             | Type      | Labels                                                                     | Purpose                                                                                                                                            |
|--------------------------------------------------------------------|-----------|----------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `coder_ai_gateway_interceptions_total`                             | counter   | `client`, `initiator_id`, `method`, `model`, `provider`, `route`, `status` | Intercepted requests.                                                                                                                              |
| `coder_ai_gateway_interceptions_inflight`                          | gauge     | `model`, `provider`, `route`                                               | Intercepted requests currently being processed.                                                                                                    |
| `coder_ai_gateway_interceptions_duration_seconds`                  | histogram | `model`, `provider`                                                        | Total intercepted request duration, including upstream processing.                                                                                 |
| `coder_ai_gateway_passthrough_total`                               | counter   | `method`, `provider`, `route`                                              | Requests passed through to an upstream provider without interception.                                                                              |
| `coder_ai_gateway_prompts_total`                                   | counter   | `client`, `initiator_id`, `model`, `provider`                              | Prompts issued by users.                                                                                                                           |
| `coder_ai_gateway_tokens_total`                                    | counter   | `client`, `initiator_id`, `model`, `provider`, `type`                      | Tokens used by intercepted requests.                                                                                                               |
| `coder_ai_gateway_injected_tool_invocations_total`                 | counter   | `model`, `name`, `provider`, `server`                                      | Invocations of MCP tools injected by AI Gateway.                                                                                                   |
| `coder_ai_gateway_non_injected_tool_selections_total`              | counter   | `model`, `name`, `provider`                                                | Tools selected by a model for the client to invoke.                                                                                                |
| `coder_ai_gateway_circuit_breaker_state`                           | gauge     | `endpoint`, `model`, `provider`                                            | Current circuit-breaker state: `0` for closed, `0.5` for half-open, and `1` for open.                                                              |
| `coder_ai_gateway_circuit_breaker_trips_total`                     | counter   | `endpoint`, `model`, `provider`                                            | Times a circuit breaker transitioned to the open state.                                                                                            |
| `coder_ai_gateway_circuit_breaker_rejects_total`                   | counter   | `endpoint`, `model`, `provider`                                            | Requests rejected because a circuit breaker was open.                                                                                              |
| `coder_ai_gateway_key_pool_state`                                  | gauge     | `provider`, `state`                                                        | Provider keys in each state: `valid`, `temporary`, or `permanent`.                                                                                 |
| `coder_ai_gateway_key_pool_state_transitions_total`                | counter   | `provider`, `reason`                                                       | Provider key state transitions during failover.                                                                                                    |
| `coder_ai_gateway_key_pool_exhaustions_total`                      | counter   | `outcome`, `provider`                                                      | Times a provider key pool had no usable key.                                                                                                       |
| `coder_ai_gateway_key_pool_failover_attempts`                      | histogram | `provider`                                                                 | Keys attempted before a request succeeded or exhausted the provider key pool.                                                                      |
| `coder_ai_gateway_provider_info`                                   | gauge     | `provider_name`, `provider_type`, `status`                                 | Build status of each configured provider, including disabled and errored ones. Value is always `1`; `status` is `enabled`, `disabled`, or `error`. |
| `coder_ai_gateway_providers_last_reload_timestamp_seconds`         | gauge     |                                                                            | Unix timestamp of the last attempt to rebuild the Gateway provider pool.                                                                           |
| `coder_ai_gateway_providers_last_reload_success_timestamp_seconds` | gauge     |                                                                            | Unix timestamp of the last successful rebuild of the Gateway provider pool.                                                                        |

Histograms also emit the standard `_bucket`, `_sum`, and `_count` series.

### Cost control metrics

Budget enforcement runs in `coderd`.
Cost control metrics are exported only from the `coderd` Prometheus listener.
Standalone replicas do not export them.

| Metric                                                             | Type      | Labels                                                 | Purpose                                                                                                                                                                                                                                                                                                                                                                                                           |
|--------------------------------------------------------------------|-----------|--------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `coder_ai_gateway_cost_control_blocked_requests_total`             | counter   | `group_id`                                             | AI requests blocked because the initiator's budget was exceeded.                                                                                                                                                                                                                                                                                                                                                  |
| `coder_ai_gateway_cost_control_blocked_users`                      | gauge     | `group_id`                                             | Users currently over their AI budget.                                                                                                                                                                                                                                                                                                                                                                             |
| `coder_ai_gateway_cost_control_enforcement_duration_seconds`       | histogram | `outcome`                                              | Duration of AI budget enforcement checks. `outcome` is `allowed`, `blocked`, or `error`.                                                                                                                                                                                                                                                                                                                          |
| `coder_ai_gateway_cost_control_unpriced_token_usage_records_total` | counter   | `model`, `provider`, `provider_model`, `provider_type` | Recorded token-usage records for which no price was found for either the requested or the provider-reported model. `provider` is the provider instance name, and `provider_type` is the configured type the price is keyed on, or `unknown` when the provider could not be resolved. `model` is the requested model, and `provider_model` is the model the provider reported, or empty when it didn't report one. |

### AI Gateway Proxy metrics

AI Gateway Proxy exports metrics from the `coderd` Prometheus listener.

A `proxy_excluded` status means another enabled provider with the same base URL hostname claimed the proxy route first. The proxy classifier uses first-wins by database name sort order (`ORDER BY name ASC`), so the first provider in that order wins and subsequent providers with the same hostname are excluded from proxy routing. They remain reachable via direct routing at `/api/v2/ai-gateway/{name}/...`.

When alerting on `coder_ai_gateway_proxy_provider_info`, exclude
`proxy_excluded` from the alert expression unless you want to be
notified of intended duplicate-hostname configurations:
`status!~"enabled|proxy_excluded"`.

| Metric                                                                   | Type    | Labels                                     | Purpose                                                                                                                           |
|--------------------------------------------------------------------------|---------|--------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `coder_ai_gateway_proxy_connect_sessions_total`                          | counter | `type`                                     | CONNECT sessions established, classified as `mitm` or `tunneled`.                                                                 |
| `coder_ai_gateway_proxy_mitm_requests_total`                             | counter | `provider`                                 | MITM requests handled by AI Gateway Proxy.                                                                                        |
| `coder_ai_gateway_proxy_inflight_mitm_requests`                          | gauge   | `provider`                                 | MITM requests currently being processed.                                                                                          |
| `coder_ai_gateway_proxy_mitm_responses_total`                            | counter | `code`, `provider`                         | MITM responses by HTTP status code.                                                                                               |
| `coder_ai_gateway_proxy_provider_info`                                   | gauge   | `provider_name`, `provider_type`, `status` | Routing status of each configured provider. Value is always `1`; `status` is `enabled`, `disabled`, `error`, or `proxy_excluded`. |
| `coder_ai_gateway_proxy_providers_last_reload_timestamp_seconds`         | gauge   |                                            | Unix timestamp of the last attempt to rebuild the proxy routing snapshot.                                                         |
| `coder_ai_gateway_proxy_providers_last_reload_success_timestamp_seconds` | gauge   |                                            | Unix timestamp of the last successful rebuild of the proxy routing snapshot.                                                      |

Refer to the [Prometheus reference](../../admin/integrations/prometheus.md) for these metrics alongside the other metrics that Coder components export.

### Metric name migration

> [!IMPORTANT]
> The embedded gateway metric prefix changed from `coder_aibridged_*` to `coder_ai_gateway_*`, and the proxy prefix changed from `coder_aibridgeproxyd_*` to `coder_ai_gateway_proxy_*`.
> The embedded gateway and AI Gateway Proxy emit the legacy names with identical values during the v2.35 and v2.36 deprecation window, and the legacy names are planned for removal in v2.37.
> The cost control metrics were added after the rename and have no legacy alias.
> The standalone gateway emits only the current `coder_ai_gateway_*` names.
> Migrate dashboards and alerts to the new names.
> Do not relabel new names back to old names while both are emitted because this creates duplicate legacy series in the same scrape.
> After the legacy names are removed, use `metric_relabel_configs` only if you need a temporary compatibility bridge:
>
> ```yaml
> metric_relabel_configs:
>   # Proxy rule must come first; the gateway regex below also matches proxy metrics.
>   - source_labels: [__name__]
>     regex: 'coder_ai_gateway_proxy_(.*)'
>     target_label: __name__
>     replacement: 'coder_aibridgeproxyd_${1}'
>   - source_labels: [__name__]
>     regex: 'coder_ai_gateway_(.*)'
>     target_label: __name__
>     replacement: 'coder_aibridged_${1}'
> ```

### Suggested alerts

Alert on any provider entering a non-`enabled` status:

```promql
sum by (instance, provider_name, status) (
  coder_ai_gateway_provider_info{status!="enabled"}
) > 0
```

Alert when the provider reload loop is firing but failing to refresh the pool for longer than a few minutes:

```promql
(coder_ai_gateway_providers_last_reload_timestamp_seconds
  - coder_ai_gateway_providers_last_reload_success_timestamp_seconds) > 300
```

Use the `coder_ai_gateway_proxy_*` metrics when you alert on AI Gateway Proxy.

## Standalone gateway monitoring

### Metrics listener

Enable the standalone metrics listener with `CODER_PROMETHEUS_ENABLE=true` or `--prometheus-enable`, and set its bind address with `CODER_PROMETHEUS_ADDRESS` or `--prometheus-address`.
The command default is `127.0.0.1:2112`.
The listener is unauthenticated, so expose it only to your monitoring network.

In addition to the common `coder_ai_gateway_*` metrics, the standalone listener exports standard unprefixed `go_*`, `process_*`, and `promhttp_*` metrics for the standalone process and its metrics handler.

### Kubernetes discovery

The [AI Gateway Helm chart](../../../helm/ai-gateway/README.md#metrics) enables metrics and binds the listener to `0.0.0.0:2112` by default.
The chart exposes a named `metrics` container port, but it does not include this port in the data-plane Service or create monitoring discovery resources.
For Prometheus pod-based discovery, add scrape annotations to each gateway pod:

```yaml
coder:
  podAnnotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "2112"
```

You can also configure a `PodMonitor` to select the chart's `app.kubernetes.io/name` and `app.kubernetes.io/instance` pod labels, or add dedicated selector labels with `coder.podLabels`.
Manage the `PodMonitor` separately or include it in the Helm release with `extraTemplates`.
To use a `ServiceMonitor`, create a separate Service that exposes the `metrics` container port because the chart's data-plane Service exposes only the HTTP traffic port.
Refer to the [Helm chart metrics configuration](../../../helm/ai-gateway/README.md#metrics) for the available chart settings.

### Health and readiness

A standalone AI gateway exposes health endpoints on its data-plane listener:

| Endpoint   | Success condition                                                                                        |
|------------|----------------------------------------------------------------------------------------------------------|
| `/healthz` | The HTTP listener is serving.                                                                            |
| `/readyz`  | The control connection to `coderd` is active and the initial provider configuration fetch has completed. |

`/readyz` returns HTTP 503 until the initial provider configuration fetch completes and whenever the control connection to `coderd` is unavailable.
The initial fetch can return an empty provider set.
A `200 OK` response from `/healthz` only means the HTTP listener is accepting connections. It returns `200 OK` even when the control connection is down.
Both endpoints are unauthenticated, bypass the concurrency, rate limiting, and BYOK middleware, and do not create trace spans.

The standalone Helm chart enables a `/healthz` liveness probe and a `/readyz` readiness probe by default.
The startup probe is disabled by default.

## Logs

### Standalone operational logs

Standalone replicas use the standard Coder logging options.
Configure them on every replica or through `coder.env` in the AI Gateway Helm chart.
Refer to the [`coder ai-gateway start` logging options](../../reference/cli/ai-gateway/start.md#-l---log-filter) for configuration details.

### Structured interception logs

AI Gateway can emit a structured log for every interception record to an external SIEM or observability platform.
`CODER_AI_GATEWAY_STRUCTURED_LOGGING` enables the records, and `CODER_AI_GATEWAY_STRUCTURED_LOGGING_SOURCE` selects which process emits them.
Under the default source, `coderd`, standalone replicas send interception records to `coderd`, which writes the structured logs to the `coderd` log output.
Set the source to `gateway` or `both` on every process to have the gateway emit its own records, and ship the gateway's logs as well as `coderd`'s.
Refer to [structured logging](./setup.md#structured-logging) for configuration and record types, and [choose which process emits the records](./setup.md#choose-which-process-emits-the-records) for the trade-offs between the sources.

## Export data

AI Gateway interception data can be exported for external analysis, compliance reporting, or integration with log aggregation systems.

### REST API

You can retrieve AI Gateway sessions via the Coder API, with filtering and pagination support.

```sh
curl -X GET "https://coder.example.com/api/v2/ai-gateway/sessions" \
  -H "Coder-Session-Token: $CODER_SESSION_TOKEN"
```

Available query filters:

- `client` - Filter by client name. Possible values are listed below.
- `initiator` - Filter by user ID or username
- `provider` - Filter by AI provider (e.g., `openai`, `anthropic`)
- `model` - Filter by model name
- `started_after` - Filter sessions after a timestamp
- `started_before` - Filter sessions before a timestamp

<details>
<summary>Possible <code>client</code> values</summary>

> [!NOTE]
> Client classification is done on best effort basis using the `User-Agent` header;
> not all clients send these headers in an easily-identifiable manner.

- `Claude Code`
- `Codex`
- `Zed`
- `GitHub Copilot (VS Code)`
- `GitHub Copilot (CLI)`
- `Kilo Code`
- `Roo Code`
- `Coder Agents`
- `Xum`
- `Cursor`
- `OpenCode`
- `Charm Crush`
- `Junie`
- `Unknown`

</details>

Refer to the [API documentation](../../reference/api/aigateway.md) for full details.

## Data retention

AI Gateway data is retained for **60&nbsp;days by default**.
Configure the retention period to balance storage costs with your organization's compliance and analysis needs.

For configuration options and details, refer to [Data Retention](./setup.md#data-retention)
in the AI Gateway setup guide.

## Tracing

AI Gateway supports tracing through [OpenTelemetry](https://opentelemetry.io/) for request processing, upstream API calls, and MCP server interactions.
Embedded gateway spans are emitted by the `coderd` process.
Standalone spans are emitted independently by every replica with the service name `coder-ai-gateway`.

### Enable tracing

AI Gateway exports spans over OTLP/gRPC when you set `CODER_TRACE_ENABLE`, honoring `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`.
The exporter always dials without TLS, so an `https://` endpoint is still contacted over plaintext gRPC.
`CODER_TRACE_HONEYCOMB_API_KEY` adds a Honeycomb exporter and works with or without `CODER_TRACE_ENABLE`.
Set only the Honeycomb key to export to Honeycomb alone, or set both to export to Honeycomb and an OTLP collector.

The embedded and standalone gateways support the same tracing configuration options, but each standalone replica must be configured separately.
Refer to the [`coder server` tracing options](../../reference/cli/server/index.md#--trace) for the embedded gateway and the [`coder ai-gateway start` tracing options](../../reference/cli/ai-gateway/start.md#--trace) for standalone replicas.
Configure tracing on every standalone process or through `coder.env` in the AI Gateway Helm chart.

The following minimal configuration enables tracing and exports spans over OTLP/gRPC:

```sh
export CODER_TRACE_ENABLE=true
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=http://otel-collector:4317
```

In both deployment modes, each request to the gateway's LLM API endpoint creates an HTTP request span, including requests that are passed through or rejected instead of intercepted.

### Traced operations

AI Gateway creates spans for the following operations:

| Span name                                   | Description                                          |
|---------------------------------------------|------------------------------------------------------|
| `CachedBridgePool.Acquire`                  | Acquiring a request bridge instance from the pool    |
| `Intercept`                                 | Top-level span for processing an intercepted request |
| `Intercept.CreateInterceptor`               | Creating the request interceptor                     |
| `Intercept.ProcessRequest`                  | Processing the request through the bridge            |
| `Intercept.ProcessRequest.Upstream`         | Forwarding the request to the upstream AI provider   |
| `Intercept.ProcessRequest.ToolCall`         | Executing a tool call requested by the AI model      |
| `Intercept.RecordInterception`              | Creating the interception record                     |
| `Intercept.RecordPromptUsage`               | Recording prompt and message data                    |
| `Intercept.RecordTokenUsage`                | Recording token consumption                          |
| `Intercept.RecordToolUsage`                 | Recording tool and function calls                    |
| `Intercept.RecordModelThought`              | Recording model reasoning                            |
| `Intercept.RecordInterceptionEnded`         | Recording the interception as completed              |
| `Passthrough`                               | Forwarding a non-intercepted provider request        |
| `ServerProxyManager.Init`                   | Initializing MCP server proxy connections            |
| `StreamableHTTPServerProxy.Init`            | Setting up HTTP-based MCP server proxies             |
| `StreamableHTTPServerProxy.Init.fetchTools` | Fetching available tools from MCP servers            |

Example trace of an interception using a Jaeger backend:

![Trace of interception](../../images/aibridge/jaeger_interception_trace.png)

### Capture logs in traces

> [!NOTE]
> Enabling log capture may generate a large volume of trace events.

Set `CODER_TRACE_LOGS=true` to include log messages as trace events:

```sh
export CODER_TRACE_ENABLE=true
export CODER_TRACE_LOGS=true
```

Log capture only applies to recording spans, so it requires tracing to be enabled through `CODER_TRACE_ENABLE` or a backend-specific exporter such as `CODER_TRACE_HONEYCOMB_API_KEY`.
Leave `CODER_TRACE_LOGS` unset to trace without capturing logs.
For standalone replicas, set both options on every process that should capture logs.

---

# AI Governance Cost Control

Source: https://coder.com/docs/ai-coder/ai-gateway/cost-controls

> [!NOTE]
> AI Gateway is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

AI Governance Cost Control governs AI spend in two complementary ways:

- **Enforcement** stops a user's requests routed via AI Gateway once their
  spend reaches their budget.
- **Reporting** shows what each user and group has approximately spent in the
  current budget period.

AI Governance Cost Control requires:

- Coder v2.36 or later.
- AI Gateway [enabled and configured](./setup.md) with at least one provider.

> [!NOTE]
> AI Governance Cost Control reports approximate spend rather than billed cost.
> These figures will not match your provider invoices exactly. For details, visit [How spend is calculated](#how-spend-is-calculated).

These terms appear throughout this page and in the Coder dashboard:

| Term                  | What it means                                                                         | Where it is set                        |
|-----------------------|---------------------------------------------------------------------------------------|----------------------------------------|
| **Budget period**     | The window spend accumulates in before it resets. Defaults to the UTC calendar month. | Deployment settings                    |
| **Budget policy**     | The rule that selects a user's effective group. Defaults to the highest budget.       | Deployment settings                    |
| **Group budget**      | A spend limit granted to each member of a group.                                      | **Groups** > {group} > **Settings**    |
| **User override**     | A spend limit for one user that supersedes their group budget.                        | **Groups** > {group} > **Members** tab |
| **Effective group**   | The group that supplies a user's budget and has their spend associated with it.       | Resolved automatically                 |
| **Approximate spend** | A user's approximate spend in the current budget period.                              | Calculated from usage                  |

## Deployment settings

Two deployment-wide settings govern budget resolution and the reset window. Each
accepts a single value today.

| Setting       | Flag                 | Environment variable     | Supported values | Default   |
|---------------|----------------------|--------------------------|------------------|-----------|
| Budget policy | `--ai-budget-policy` | `CODER_AI_BUDGET_POLICY` | `highest`        | `highest` |
| Budget period | `--ai-budget-period` | `CODER_AI_BUDGET_PERIOD` | `month`          | `month`   |

- **Budget policy** determines which budget wins when a user belongs to more
  than one budgeted group. `highest` selects the largest.
- **Budget period** sets the reset window. `month` is the UTC calendar month, so
  spend resets at 00:00 UTC on the first day of each month.

These settings are deployment-wide.

## Budget

**Every user's spend is recorded against a group.** A user only has a budget
when one is set on a group they belong to, or when they are given a user
override.

> [!NOTE]
> When AI Governance Cost Control is first deployed, users have **unlimited
> spend** until an administrator sets budgets. Their spend is recorded against
> the `Everyone` group.

### Group budget

Setting a group budget requires the Owner, User Admin, Organization Admin, or Organization User Admin role.
Refer to [Groups and roles](../../admin/users/groups-roles.md) for the deployment roles.
The [Organization roles](../../admin/users/groups-roles.md#organization-roles) section covers the organization roles.

A group budget applies to each member individually rather than to the group as a
whole. For example, if a group has ten members and a budget of $200 USD, each
member can spend $200 USD and the group has a total spend limit of $2,000 USD.

1. Go to **Groups** and select a group.
1. Select **Settings**.
1. Under **AI budget**, set **Monthly limit per member**.
1. Select **Save**.

![Group AI budget settings](../../images/aibridge/group-ai-budget.png)

Budget values behave as follows:

- An empty field means no budget is set. The field displays `no budget`.
- `$0 USD` blocks every request routed via AI Gateway from members whose
  effective group is this group.
- The maximum is `$1,000,000 USD` per member per budget period.

Note: Members who belong to other groups with budgets are still governed by
whichever group the budget policy selects. See
[Effective group resolution](#effective-group-resolution).

### User override

Adding or removing an override requires the Owner or User Admin
[role](../../admin/users/groups-roles.md). Other administrator roles can view
overrides but cannot change them.

Override a group budget when one user needs a different limit from the rest of
their group.

1. Go to **Groups**, select a group, then open the **Members** tab.
1. Find the member to apply the override to, open their action menu, and select
   **Manage AI budget**.
1. Enable **Override group budget**.
1. Set **Custom monthly budget**, then choose the group in
   **Budget assigned to**.
1. Select **Update**.

![User AI budget override](../../images/aibridge/user-override-ai-budget.png)

Overrides behave as follows:

- A user can have only one override at a time.
- An override supersedes every group budget the user belongs to.
- Spend is always attributed to a group, so an override must name the assigned
  group. This group can be different from the group selected in the **Members**
  tab. The user must belong to the assigned group.
- The `$0 USD` to `$1,000,000 USD` range applies to overrides as well.
- Disabling **Override group budget** removes the override and returns the user
  to the budget of their [effective group](#effective-group-resolution).

### Effective group resolution

A user can belong to several groups that have budgets, and can also hold an
override. AI Gateway resolves a single effective group for each request, in this
order:

1. The user's [override](#user-override) takes precedence over every group
   budget.
1. Otherwise, the [budget policy](#deployment-settings) selects one of the
   groups the user belongs to. The default policy, `highest`, selects the group
   with the largest budget.
1. If none of those groups has a budget, the user has *effectively* unlimited
   spend and their spend is recorded against the `Everyone` group.

> [!NOTE]
> Groups with identical budgets are ranked by the organization membership the
> user joined first, then by group ID. To see the effective group currently
> assigned to a user, see [Monitor spend](#monitor-spend). The effective group is
> deployment-wide, so it can be a group in a different organization.

Recorded spend is immutable. Changing which budget applies to a user affects
future requests only: spend that Coder has already recorded stays with the group
it was attributed to, so a user's history can span several groups. The effective
group is resolved at request time, so changing a group budget can change which
group applies to a user on future requests.

## How enforcement works

AI Gateway checks each request before forwarding it upstream. The check compares
the user's spend in the current budget period with the budget that applies to the
request:

- Spend below the budget: the request proceeds.
- Spend at or above the budget: AI Gateway returns `403 Forbidden` with a
  message that describes the issue.

Users without a budget have **unlimited spend**, so their requests proceed
without enforcement. A blocked user's access resumes when the budget period
resets, when an administrator raises the budget, or when an override is added.

> [!NOTE]
> Enforcement is approximate. A request's cost is known only after the provider
> response reaches AI Gateway, so concurrent in-flight requests can carry a user
> slightly past their budget. Subsequent requests are blocked after the recorded
> spend reaches the budget.

### Notifications

The first time a user's spend crosses a threshold within a budget period, Coder
notifies the user and deployment-wide Owners and User Admins, excluding the
affected user:

| Threshold | User notification              | Admin notification                       |
|-----------|--------------------------------|------------------------------------------|
| 85%       | You're approaching your budget | `<username>` is approaching their budget |
| 100%      | You've reached your budget     | `<username>` has reached their budget    |

- A single expensive request can cross both thresholds at once.
- Budgets of `$0 USD` and unpriced usage cross no thresholds.
- Notifications are informational. Enforcement does not depend on them.

Owners also receive **Missing AI Model Prices** weekly, listing models used in the past week that have no price.

For delivery methods, see
[Notifications](../../admin/monitoring/notifications/index.md).

## How spend is calculated

Coder multiplies the token usage of each request by the published price of its model.
Prices come from a curated [models.dev](https://models.dev) snapshot that ships with every Coder release, so no configuration is required.

Coder prices a request by the model the client requested.
When that model has no price, Coder uses the price of the model the provider reports serving, for example when the provider resolves an alias to a specific model.
Coder uses the first price it finds, in this order:

1. A custom price for the requested model.
1. The default price for the requested model.
1. A custom price for the model the provider reports.
1. The default price for the model the provider reports.

A price for the requested model always takes precedence, even when the model the provider reports has a custom price.

Spend accumulates only from the moment v2.36 is deployed. Upgrading mid-month
therefore produces a partial first period.

To see the prices this deployment uses, list them. The `source` column reports
whether each is a default price or a custom price set on this deployment:

```sh
coder exp ai-model-prices list
```

A custom price takes precedence over its default, so it is the one listed. To
see the default for such a model, filter to it:

```sh
coder exp ai-model-prices list --source default
```

Default prices come from the price book that ships with each Coder release. To
see the price book for a release:

```text
https://github.com/coder/coder/blob/release/<VERSION>/coderd/aibridge/prices/data/prices.json
```

Replace `<VERSION>` with a Coder minor version, for example `2.36`.

To use your own price for any of these models, see
[Configure model prices](#configure-model-prices).

> [!IMPORTANT]
> Spend is an approximation. It can differ from what the provider bills, and
> some usage does not count toward it at all:
>
> - Default prices are list prices. A custom price brings spend closer to the
>   rates a deployment actually pays, though billing rules that are not a
>   per-token rate, such as committed-use discounts, cannot be represented.
> - A model with no price adds nothing to spend. Its token usage is still
>   recorded, but it never counts toward a limit, so a user who calls only
>   unpriced models is effectively unlimited. Setting a price for the model
>   closes the gap.

Monitor `coder_ai_gateway_cost_control_unpriced_token_usage_records_total`, labeled by `provider`, `provider_type`, `model`, and `provider_model`, to detect unpriced usage.
`model` is the model the client requested, and `provider_model` is the model the provider reported, or empty when the provider didn't report one.
Set a price for either model under its `provider_type` to close the gap.
Any non-zero value means spend is under-counted.
Because the price book ships with the release, a newly launched model is unpriced until you upgrade Coder or set a price for it yourself.

Coder also notifies Owners weekly about models used in the past week that have no price.

### Configure model prices

Use the experimental `coder exp ai-model-prices` command to set model prices
for your deployment. It requires AI Governance, which is included with a
Premium license, and the Owner
[role](../../admin/users/groups-roles.md) or a custom role granting
`ai_model_price:update`. Run `coder exp ai-model-prices --help` for the full
reference.

List the prices this deployment holds, optionally narrowed to one provider or
model. The `source` column reports whether a price is a default price
(`default`) or one set on this deployment (`custom`):

```sh
coder exp ai-model-prices list --provider anthropic
```

List only the prices you have set:

```sh
coder exp ai-model-prices list --source custom
```

A listing reports one price per model, so an overridden model's default is not
shown. To see every price a model holds, both at once:

```sh
coder exp ai-model-prices list --source all
```

Price a single model. Prices are micro-units per million tokens, so `3000000`
is $3.00 per million tokens. Use `null` for a price you do not have, and `0` to
declare a model free:

```sh
coder exp ai-model-prices update --provider anthropic --model my-model \
  --input-price 3000000 --output-price 15000000 \
  --cache-read-price null --cache-write-price null
```

Price several models at once from a JSON document in the same shape as the
price book:

```sh
coder exp ai-model-prices update prices.json
```

> [!IMPORTANT]
>
> - Prices are not retroactive. Usage recorded before you set a price stays
>   unpriced, so past spend does not change.
> - A price you set takes precedence over the default and stays in effect
>   across upgrades, so it does not pick up later price books.
> - A price is keyed by provider type and model, so every configured provider
>   of that type shares it.
> - `openai-compat` providers cannot be priced. They pass through to any
>   upstream vendor, so a single price would be wrong for most of them.
> - This command is experimental and can change without notice.

## Monitor spend

Spend reporting is available in the Coder dashboard and as a CSV export.
Prometheus metrics report enforcement and pricing gaps.

### Dashboard

Visibility follows the viewer's role:

| Who                                                  | Sees                                                                 |
|------------------------------------------------------|----------------------------------------------------------------------|
| Every user                                           | Their own spend and budget, or unlimited state, in their avatar menu |
| Members of a group                                   | The group's spend and budget, and their own member row               |
| Owners, User Admins, and organization administrators | Spend and budgets for every group and every member                   |

<!-- TODO(AIGOV-685): Restore once the User spend page moves out of experimental.
| Readers of an organization's group members           | Organization totals and per-user spend on the **User spend** page    |

- The **User spend** page under **Admin settings** > **AI** shows total and per-user AI Gateway spend for the selected organization and reporting period.
  You can open it if you can read the organization's group members, as Owners, Auditors, Template Admins, User Admins, and their organization-scoped equivalents can.
  If you can also view AI sessions, you can filter it by provider, model, and client.
-->

- The **Groups** page compares each group's spend with the combined limits of
  the members it covers.
- The **Members** tab of a group reports each member's spend, their budget, and
  its source, labeled `Custom limit` for an override or `Group limit` for a
  group budget. If the effective group is another group in the same organization,
  the row shows `Budget managed by another group`. If the effective group is in a
  different organization, the row shows a dash and explains that the group is not
  visible there. Because the organization's `Everyone` group includes every
  member, its **Members** tab is a quick way to look up any user's effective
  group.
- The avatar menu reports the signed-in user's own spend for the budget period
  as `$<spend> / $<budget> USD`, or `$<spend> / Unlimited USD` when no budget
  applies.

Administrators can also use the
[Get user AI spend](../../reference/api/enterprise.md#get-user-ai-spend) API
endpoint to see a user's current effective group.

### Spend export

If you can read the organization's group members, you can export approximate spend for reporting and internal cost allocation.

```sh
curl -H "Coder-Session-Token: $CODER_SESSION_TOKEN" \
  "https://coder.example.com/api/v2/organizations/<organization>/ai/spend/export"
```

- Without parameters, the export covers the current budget period.
- To select a range, pass `period_start` and `period_end` together as RFC 3339 timestamps.
  A range can span at most 31&nbsp;days.
- Spend is attributed through each request's effective budget group, which falls back to the organization's `Everyone` group when no budget applies, so only usage recorded without any effective group is excluded.
- Each CSV row breaks spend down by user, group, model, and provider, with the underlying token counts.

<!-- TODO(AIGOV-685): Restore once the per-user spend endpoint moves out of /api/experimental.
For programmatic per-user reporting, refer to the [List organization AI spend by user API reference](../../reference/api/enterprise.md#list-organization-ai-spend-by-user).
-->

### Prometheus Metrics

Prometheus metrics report blocked requests, users over budget, unpriced usage,
and enforcement latency. For the full metric list, including types and labels,
see [Prometheus metrics](../../admin/integrations/prometheus.md).

## Migrate from Coder Agents Cost Control

In v2.36, AI Governance Cost Control replaces Coder Agents Cost Control. The
legacy Coder Agents Spend page remains available until v2.37.

> [!WARNING]
> Spend limits configured under **Admin settings** > **AI** > **Spend** are no
> longer enforced by Coder Agents. To enforce spend, set an AI Governance budget.

To migrate existing limits:

1. Record the limits currently set under **Admin settings** > **AI** >
   **Spend**, including the default limit and any group or user overrides.
1. Recreate group limits as [group budgets](#group-budget).
1. Recreate per-user limits as [user overrides](#user-override).

Expect the following differences:

- No deployment-wide default exists. Each group that needs a limit requires its
  own budget.
- The UTC calendar month is the only period. Daily and weekly periods are not
  currently supported.
- Users in several budgeted groups receive the highest budget. Coder Agents Cost
  Control applied the lowest.
- Budgets cover priced AI Gateway traffic. Chat, IDE extensions, and CLI agents
  draw on the same budget when their provider and model are priced. See
  [How spend is calculated](#how-spend-is-calculated).
- Recorded spend does not carry over. Every user starts the first period at
  $0 USD.
- Coder Agents users who exceed their budget see a usage limit error in chat.
  The error details include the AI Governance budget limit.

## Cost controls without conversation content

Cost control reads none of the tables that store prompts, tool call arguments or model thoughts.
It depends only on the interception and token usage records, the model prices and the budget tables.

A deployment that wants budgets and spend reporting without retaining conversation content can therefore set
[`--ai-gateway-disable-content-recording`](./setup.md#disable-content-recording) and keep every cost control feature on this page.

> [!NOTE]
> [`--ai-gateway-retention`](./setup.md#data-retention) can't do this.
> It purges the interception and token usage records too, so it sheds the cost ledger along with the content.

## Next steps

- [Monitoring](./monitoring.md)
- [Auditing AI sessions](./audit.md)
- [AI Gateway API reference](../../reference/api/enterprise.md)

---

# Reference

Source: https://coder.com/docs/ai-coder/ai-gateway/reference

> [!NOTE]
> AI Gateway is part of [AI Governance](../ai-governance.md), which is
> included with a Premium license.

## Deployment topologies

AI Gateway can run inside `coderd` or as a standalone data-plane service.
Both topologies run the same gateway request handling and keep `coderd` as the source of truth for Coder API key validation, provider configuration, and AI session records.
They differ in how requests are routed to the gateway.

### Embedded gateway

By default, `coder server` runs an in-memory gateway instance in the `coderd` process.
AI clients send requests to `<Coder access URL>/api/v2/ai-gateway/<provider-name>/`.
The embedded gateway uses the same control RPC as a standalone deployment, over an in-process transport rather than a network connection.
It does not use a gateway key and does not negotiate an AI Gateway API version.

The following diagram shows the embedded topology:

![AI Gateway implementation details](../../images/aibridge/aibridge-implementation-details.png)

### Standalone gateway

A [standalone deployment](./standalone.md) runs the AI traffic data plane outside the `coderd` process.
Each replica accepts client traffic, sends AI requests directly to upstream providers, and maintains a control connection to `coderd` by using a [gateway key](./standalone.md#create-a-gateway-key).

The control connection carries the following:

- Coder API key validation, which resolves each request to an active Coder user.
- AI budget checks, which reject requests from users over their spend limit.
- Provider configuration, plus a change signal when the provider set changes.
- AI session records.
- **Deprecated**: the configuration and access tokens used by [injected MCP](./mcp.md).

Standalone replicas have no authoritative database state.
They keep ephemeral provider snapshots, request caches, provider key pools, and metrics in memory, and emit their own logs and traces.
When API dumps are enabled, each replica writes its own [API dumps](./setup.md#api-dumps) to its own local disk.

`coderd` remains required for standalone operation.
A replica becomes unready when its control connection is unavailable, even if its HTTP listener remains healthy.
AI Gateway Proxy remains part of `coderd` and can forward its intercepted traffic to either the embedded gateway or a standalone endpoint.

## Version compatibility

The control connection between a standalone replica and `coderd` uses a versioned AI Gateway API.
The current AI Gateway API version is defined in [`coderd/aibridged/proto/version.go`](../../../coderd/aibridged/proto/version.go).

`coderd` validates the AI Gateway API version that a standalone replica advertises before it accepts the control connection.
AI Gateway API compatibility follows these rules:

- The gateway and `coderd` AI Gateway API major versions must match.
- The gateway's AI Gateway API minor version must be less than or equal to the `coderd` instance's AI Gateway API minor version.
- `coderd` rejects a standalone gateway that advertises a newer AI Gateway API minor version.

A rejected replica receives an HTTP 400 response that reports the `client_api_version` and `server_api_version` values.
Coder build versions are not the compatibility criterion.

For upgrade and rollback ordering, refer to [Version compatibility](./standalone.md#version-compatibility) in the standalone deployment guide.

## Actor header forwarding

Enable `--ai-gateway-send-actor-headers`, `CODER_AI_GATEWAY_SEND_ACTOR_HEADERS`, or `ai_gateway.send_actor_headers` to add actor identity to intercepted upstream requests.
The setting is disabled by default.

When actor forwarding is enabled, AI Gateway uses these default header settings:

| Actor attribute | Default header                        | Value                                              |
|-----------------|---------------------------------------|----------------------------------------------------|
| `id`            | `X-AI-Bridge-Actor-ID`                | The authenticated Coder user ID.                   |
| `username`      | `X-AI-Bridge-Actor-Metadata-Username` | The username from the authenticated Coder account. |
| `email`         | *(empty)*                             | The authenticated Coder account email address.     |

Configure the ID header with `--ai-gateway-actor-header-id`, `CODER_AI_GATEWAY_ACTOR_HEADER_ID`, or `ai_gateway.actor_header_id`.
Configure the username header with `--ai-gateway-actor-header-username`, `CODER_AI_GATEWAY_ACTOR_HEADER_USERNAME`, or `ai_gateway.actor_header_username`.
Configure the email header with `--ai-gateway-actor-header-email`, `CODER_AI_GATEWAY_ACTOR_HEADER_EMAIL`, or `ai_gateway.actor_header_email`.

Each option uses its own precedence: the CLI flag overrides the environment variable, the environment variable overrides the YAML value, and the default applies when none is set.
Set an option to an empty value to disable that actor attribute without disabling the other attributes.
Email forwarding requires both the global `send_actor_headers` setting and a non-empty email header name.

AI Gateway uses values from the authenticated Coder account, not client-supplied headers.
For intercepted requests, AI Gateway always removes client headers whose names start with `X-AI-Bridge-Actor`, case-insensitively, even when `send_actor_headers` is disabled.
Configured actor headers are still re-injected from authenticated account values, and passthrough requests are unaffected.
AI Gateway omits the email header when the authenticated account has no email address.
Actor header settings apply to every configured provider.
Email is personal information, so set the email option only if every upstream may receive it.
Gateway does not inject actor headers on passthrough routes.

### Header name restrictions

An empty header name turns off that actor attribute.
A nonempty name must be a valid [HTTP field name](https://www.rfc-editor.org/rfc/rfc9110.html#section-5.1) as defined by RFC 9110.
Nonempty configured names must be unique, ignoring case.

You can't use any of these reserved names, regardless of casing:

- **Authentication and session**: `Authorization`, `X-Api-Key`, `Cookie`, `Set-Cookie`.
- **Transport and forwarding**: `Host`, `User-Agent`, `Content-Length`, `Content-Type`, `Content-Encoding`, `Accept-Encoding`, `Connection`, `Keep-Alive`, `Te`, `Trailer`, `Transfer-Encoding`, `Upgrade`, `Forwarded`, `X-Forwarded-For`, `X-Forwarded-Host`, `X-Forwarded-Proto`, `X-Forwarded-Port`.
- **Proxy**: `Proxy-Authorization`, `Proxy-Authenticate`.
- **Coder internal**: `Coder-Session-Token`, `X-Coder-Ai-Governance-Token`, `X-Coder-Ai-Governance-Request-Id`, `X-Coder-Agent-Firewall-Session-Id`, `X-Coder-Agent-Firewall-Sequence-Number`.

Names beginning with `X-AI-Bridge-Actor` are also reserved, ignoring case, except for the standard name of the attribute you're configuring.
For example, `X-User-ID` and `X-Username` are valid custom names.
An invalid configuration prevents `coderd` or a standalone AI Gateway from starting.

## Supported APIs

API support is divided into two categories:

- **Intercepted**: Requests are intercepted, audited, and augmented.
- **Passthrough**: Requests are proxied directly to the upstream provider without auditing or augmentation.

Where relevant, both streaming and non-streaming requests are supported.
Paths are relative to the provider's base URL, such as `https://ai-gateway.example.com/openai/v1` or `https://ai-gateway.example.com/anthropic`.

### OpenAI

The OpenAI provider also serves the Azure OpenAI, Google, OpenRouter, Vercel, and OpenAI-compatible provider types.

#### Intercepted

- [`/v1/chat/completions`](https://platform.openai.com/docs/api-reference/chat/create)
- [`/v1/responses`](https://platform.openai.com/docs/api-reference/responses/create)

#### Passthrough

- [`/v1/conversations(/*)`](https://platform.openai.com/docs/api-reference/conversations)
- [`/v1/models(/*)`](https://platform.openai.com/docs/api-reference/models/list)
- [`/v1/responses/*`](https://platform.openai.com/docs/api-reference/responses/get)

The legacy [`/v1/completions`](https://platform.openai.com/docs/api-reference/completions) API is deprecated and is not passed through.

### Anthropic

The Anthropic provider also serves the AWS Bedrock provider type.

#### Intercepted

- [`/v1/messages`](https://docs.claude.com/en/api/messages)

#### Passthrough

- [`/v1/messages/count_tokens`](https://docs.claude.com/en/api/messages-count-tokens)
- [`/v1/models(/*)`](https://docs.claude.com/en/api/models-list)
- `/api/event_logging/*`

### GitHub Copilot

#### Intercepted

- `/chat/completions`
- `/responses`
- `/v1/messages`

#### Passthrough

All Copilot routes other than the intercepted routes listed above pass through to the configured upstream provider.

## Troubleshooting

To report a bug, file a feature request, or review known issues, visit the [Coder GitHub repository](https://github.com/coder/coder/issues).
For help with AI Gateway, visit the [Coder Discord](https://discord.gg/coder).

---

# Rebranding Migration

Source: https://coder.com/docs/ai-coder/ai-gateway/rebranding-migration

AI Bridge has been renamed to **AI Gateway**. This is a cosmetic rebrand to make
the feature easier to understand. It changes user-visible names, configuration
options, the canonical HTTP API path, and the Prometheus metric names.

> [!NOTE]
> Deprecated aliases remain available for gateway and proxy controls.
> Provider configuration through environment variables, flags, and YAML has been removed under both names; refer to [Provider configuration](./providers.md#database-management-of-providers).

Adopt the `ai_gateway` names for gateway and proxy settings so your configuration matches the current documentation.

> [!IMPORTANT]
> New settings added in every area except the database (configuration options,
> environment variables, CLI flags, and API paths) will use only the new
> `ai_gateway` name, with no `aibridge` alias.

## At a glance

| Area                  | Old name                                       | New (canonical) name                              | Old name still works?              |
|-----------------------|------------------------------------------------|---------------------------------------------------|------------------------------------|
| Environment variables | `CODER_AIBRIDGE_*`                             | `CODER_AI_GATEWAY_*`                              | Yes, except provider setup         |
| CLI flags             | `--aibridge-*`                                 | `--ai-gateway-*`                                  | Yes, except provider setup         |
| YAML config group     | `aibridge:` / `aibridgeproxy:`                 | `ai_gateway:` / `ai_gateway_proxy:`               | Yes, except provider setup         |
| HTTP API              | `/api/v2/aibridge`                             | `/api/v2/ai-gateway`                              | Yes (legacy route retained)        |
| Prometheus metrics    | `coder_aibridged_*` / `coder_aibridgeproxyd_*` | `coder_ai_gateway_*` / `coder_ai_gateway_proxy_*` | Yes (both emitted, old deprecated) |
| Database              | (no change)                                    | (no change)                                       | n/a                                |

## What did not change

- **No database changes.** Table and column names (for example,
  `aibridge_interceptions`) are unchanged. No migration runs and no data is
  rewritten on upgrade.
- **Gateway and proxy settings.** Renaming options for logging, retention, or listener addresses does not change their behavior or defaults.
- **Internal/library references.** Some internal package names, log fields, and
  library identifiers still use the `aibridge` name. These are not part of the
  supported configuration surface and do not affect operators.

## Configuration (env vars, flags, YAML)

The aliases listed below apply only to gateway and proxy controls, not provider setup.

If both a previous name and a new name are set for the same setting, set only one (prefer
the new name).

### Naming rules

The rename is a mechanical substitution:

- Environment variables: `CODER_AIBRIDGE_` becomes `CODER_AI_GATEWAY_`.
- CLI flags: `--aibridge-` becomes `--ai-gateway-`.
- YAML: only the top-level group key changes
  (`aibridge:` becomes `ai_gateway:`, `aibridgeproxy:` becomes
  `ai_gateway_proxy:`). The keys nested under the group are unchanged.

### YAML example

Before:

```yaml
aibridge:
  enabled: true
  retention: 60d
aibridgeproxy:
  enabled: true
  listen_addr: ":8888"
```

After:

```yaml
ai_gateway:
  enabled: true
  retention: 60d
ai_gateway_proxy:
  enabled: true
  listen_addr: ":8888"
```

### Environment variable reference

Core AI Gateway settings:

| Deprecated                                         | New                                                  | Note |
|----------------------------------------------------|------------------------------------------------------|------|
| `CODER_AIBRIDGE_ENABLED`                           | `CODER_AI_GATEWAY_ENABLED`                           |      |
| `CODER_AIBRIDGE_INJECT_CODER_MCP_TOOLS`            | `CODER_AI_GATEWAY_INJECT_CODER_MCP_TOOLS`            |      |
| `CODER_AIBRIDGE_RETENTION`                         | `CODER_AI_GATEWAY_RETENTION`                         |      |
| `CODER_AIBRIDGE_MAX_CONCURRENCY`                   | `CODER_AI_GATEWAY_MAX_CONCURRENCY`                   |      |
| `CODER_AIBRIDGE_RATE_LIMIT`                        | `CODER_AI_GATEWAY_RATE_LIMIT`                        |      |
| `CODER_AIBRIDGE_STRUCTURED_LOGGING`                | `CODER_AI_GATEWAY_STRUCTURED_LOGGING`                |      |
| `CODER_AIBRIDGE_SEND_ACTOR_HEADERS`                | `CODER_AI_GATEWAY_SEND_ACTOR_HEADERS`                |      |
| `CODER_AIBRIDGE_ALLOW_BYOK`                        | `CODER_AI_GATEWAY_ALLOW_BYOK`                        |      |
| `CODER_AIBRIDGE_CIRCUIT_BREAKER_ENABLED`           | `CODER_AI_GATEWAY_CIRCUIT_BREAKER_ENABLED`           |      |
| `CODER_AIBRIDGE_CIRCUIT_BREAKER_FAILURE_THRESHOLD` | `CODER_AI_GATEWAY_CIRCUIT_BREAKER_FAILURE_THRESHOLD` |      |
| `CODER_AIBRIDGE_CIRCUIT_BREAKER_INTERVAL`          | `CODER_AI_GATEWAY_CIRCUIT_BREAKER_INTERVAL`          |      |
| `CODER_AIBRIDGE_CIRCUIT_BREAKER_TIMEOUT`           | `CODER_AI_GATEWAY_CIRCUIT_BREAKER_TIMEOUT`           |      |
| `CODER_AIBRIDGE_CIRCUIT_BREAKER_MAX_REQUESTS`      | `CODER_AI_GATEWAY_CIRCUIT_BREAKER_MAX_REQUESTS`      |      |

AI Gateway Proxy settings:

| Deprecated                                   | New                                            | Note                              |
|----------------------------------------------|------------------------------------------------|-----------------------------------|
| `CODER_AIBRIDGE_PROXY_ENABLED`               | `CODER_AI_GATEWAY_PROXY_ENABLED`               |                                   |
| `CODER_AIBRIDGE_PROXY_LISTEN_ADDR`           | `CODER_AI_GATEWAY_PROXY_LISTEN_ADDR`           |                                   |
| `CODER_AIBRIDGE_PROXY_TLS_CERT_FILE`         | `CODER_AI_GATEWAY_PROXY_TLS_CERT_FILE`         |                                   |
| `CODER_AIBRIDGE_PROXY_TLS_KEY_FILE`          | `CODER_AI_GATEWAY_PROXY_TLS_KEY_FILE`          |                                   |
| `CODER_AIBRIDGE_PROXY_CERT_FILE`             | `CODER_AI_GATEWAY_PROXY_CERT_FILE`             |                                   |
| `CODER_AIBRIDGE_PROXY_KEY_FILE`              | `CODER_AI_GATEWAY_PROXY_KEY_FILE`              |                                   |
| `CODER_AIBRIDGE_PROXY_UPSTREAM`              | `CODER_AI_GATEWAY_PROXY_UPSTREAM`              |                                   |
| `CODER_AIBRIDGE_PROXY_UPSTREAM_CA`           | `CODER_AI_GATEWAY_PROXY_UPSTREAM_CA`           |                                   |
| `CODER_AIBRIDGE_PROXY_ALLOWED_PRIVATE_CIDRS` | `CODER_AI_GATEWAY_PROXY_ALLOWED_PRIVATE_CIDRS` |                                   |
| `CODER_AIBRIDGE_PROXY_DUMP_DIR`              | `CODER_AI_GATEWAY_PROXY_DUMP_DIR`              |                                   |
| `CODER_AIBRIDGE_PROXY_DOMAIN_ALLOWLIST`      | `CODER_AI_GATEWAY_PROXY_DOMAIN_ALLOWLIST`      | Already deprecated; has no effect |

CLI flags follow the same mapping with the `--aibridge-*` to `--ai-gateway-*`
prefix change.

## HTTP API

The canonical API path is now `/api/v2/ai-gateway` (and
`/api/v2/ai-gateway/proxy`). The legacy `/api/v2/aibridge` and
`/api/v2/aibridge/proxy` routes are retained for backward compatibility and
continue to serve the same handlers.

If you have external integrations or agents calling the API directly, update them to the
new path at your convenience. No immediate action is required.

AI clients (such as Claude Code, Codex, and other tools) that are configured
with a base URL pointing at the legacy `/api/v2/aibridge` path continue to work,
but should be updated to the new `/api/v2/ai-gateway` base URL.

## Metrics

The metric prefixes have been renamed:

| Deprecated prefix        | New prefix                 |
|--------------------------|----------------------------|
| `coder_aibridged_*`      | `coder_ai_gateway_*`       |
| `coder_aibridgeproxyd_*` | `coder_ai_gateway_proxy_*` |

**Both the old and new metric names are emitted simultaneously today.** Every
series is exported under both prefixes from the same underlying collector, so
existing dashboards, alerts, and recording rules keep working immediately after
upgrade with no changes.

The old prefixes are retained for backward compatibility with no planned removal
date. To keep your observability aligned with the new names:

1. Update Grafana dashboards, Prometheus alerting rules, and recording rules to
   reference the new `coder_ai_gateway_*` and `coder_ai_gateway_proxy_*` names.
2. Verify the new series are present in your monitoring stack (they are emitted
   as of this release).

### Optional: dropping the old names

If you have already migrated to the new names and do not want both prefixes
ingested (for example, to avoid doubling cardinality in your time-series
database), you can drop the deprecated series at scrape time with Prometheus
`metric_relabel_configs`:

```yaml
metric_relabel_configs:
  - source_labels: [__name__]
    regex: 'coder_aibridged_.*|coder_aibridgeproxyd_.*'
    action: drop
```

This keeps the canonical `coder_ai_gateway_*` and `coder_ai_gateway_proxy_*`
series and discards the deprecated `coder_aibridged_*` and
`coder_aibridgeproxyd_*` ones before they are stored. Only do this once your
dashboards, alerts, and recording rules reference the new names.

---

# MCP Server

Source: https://coder.com/docs/ai-coder/mcp-server

Coder includes a built-in [Model Context Protocol](https://modelcontextprotocol.io/)
(MCP) server that provides AI assistants with tools and context about your Coder
deployment. This enables AI-powered workflows for managing workspaces,
templates, and development environments.

Coder supports two MCP server modes:

- **[Local MCP Server](#local-mcp-server)**: Runs via the Coder CLI using stdio
  transport. Ideal for local AI tools and IDE integrations.
- **[Remote MCP Server](#remote-mcp-server)**: HTTP-based server exposed by your
  Coder deployment. Supports OAuth2 authentication and is published to the MCP
  Registry.

## Local MCP Server

The local MCP server runs via the Coder CLI and uses stdio transport to
communicate with AI tools.

### Setup

Run the MCP server using the Coder CLI:

```sh
coder exp mcp server
```

### Client Configuration

Configure your MCP client to spawn the Coder CLI:

```json
{
  "mcpServers": {
    "coder": {
      "command": "coder",
      "args": ["exp", "mcp", "server"]
    }
  }
}
```

The CLI automatically uses your existing Coder authentication (from `coder login`).

### Claude Desktop Example

Add to your Claude Desktop configuration file:

<div class="tabs">

#### macOS

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "coder": {
      "command": "coder",
      "args": ["exp", "mcp", "server"]
    }
  }
}
```

#### Windows

Edit `%APPDATA%\Claude\claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "coder": {
      "command": "coder.exe",
      "args": ["exp", "mcp", "server"]
    }
  }
}
```

</div>

## Remote MCP Server

The remote MCP server is an HTTP endpoint exposed by your Coder deployment at
`/api/experimental/mcp/http`. This enables MCP clients to connect to Coder
without running the CLI locally.

The endpoint implements the
[Streamable HTTP transport](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports)
in stateless mode: it supports MCP specification versions from `2024-11-05`
through `2026-07-28`, does not issue `Mcp-Session-Id` headers, and answers
`GET` and `DELETE` with `405 Method Not Allowed` (there is no standalone
server-event stream or explicit session termination, both permitted by the
specification). The server exposes tools only; MCP resources, prompts,
structured tool output, elicitation, and the MCP Tasks extension are not
implemented.

### Prerequisites

The remote MCP HTTP endpoint requires the OAuth2 provider and the `mcp-server-http` experiment on your Coder deployment:

```sh
coder server --oauth2-provider-enable --experiments=mcp-server-http
```

Or set the environment variables:

```sh
CODER_OAUTH2_PROVIDER_ENABLE=true
CODER_EXPERIMENTS=mcp-server-http
```

For the YAML and Helm forms of the provider setting, refer to [Enable OAuth2 Provider](../admin/integrations/oauth2-provider/index.md#enable-oauth2-provider).
That page does not cover the experiment; set it with the top-level [`experiments`](../reference/cli/server/index.md#--experiments) YAML key.

### MCP Registry

Coder is published to the official [MCP Registry](https://github.com/modelcontextprotocol/registry)
as `io.github.coder/coder`, enabling easy installation in supported MCP clients.

#### VS Code / GitHub Copilot

1. Open VS Code Command Palette and run **MCP: Add Server...**
1. Select **From MCP Registry**
1. Search for "Coder" and select it
1. Enter your Coder deployment hostname when prompted (e.g., `coder.example.com`)
1. VS Code will automatically handle OAuth2 authentication

#### Claude Desktop (Remote)

Add to your Claude Desktop configuration file (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "coder": {
      "url": "https://coder.example.com/api/experimental/mcp/http"
    }
  }
}
```

Claude Desktop will automatically discover OAuth2 endpoints and prompt you to
authenticate through your browser.

### Manual Configuration

For MCP clients that don't support the registry or OAuth2 discovery, configure
the server manually with a session token:

```json
{
  "mcpServers": {
    "coder": {
      "url": "https://coder.example.com/api/experimental/mcp/http",
      "headers": {
        "Coder-Session-Token": "<your-session-token>"
      }
    }
  }
}
```

To create a session token:

1. Navigate to your Coder deployment
1. Go to **Settings > Tokens**
1. Create a new token
1. Add the token to your MCP client configuration

## Authentication

The MCP server supports two authentication methods:

### OAuth2 (Recommended for Interactive Clients)

MCP clients that support [RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728)
(Protected Resource Metadata) can authenticate automatically using OAuth2. The
server advertises its OAuth2 capabilities via the `WWW-Authenticate` header and
`/.well-known/oauth-protected-resource` endpoint.

This enables a seamless connect-and-authenticate experience where users sign in through their browser without manually managing tokens.

> [!NOTE]
> OAuth2 requires `CODER_OAUTH2_PROVIDER_ENABLE=true` on your Coder deployment.

### Session Token (For Programmatic Access)

For clients that don't support OAuth2 discovery, or for programmatic access, use
a session token as shown in the [Manual Configuration](#manual-configuration)
section.

## Available Tools

The MCP server exposes tools across several areas:

- **Workspace management**: list, inspect, create, and build workspaces
- **Template operations**: list, inspect, create, and manage templates and versions
- **File operations**: read, write, and edit files in a workspace
- **Workspace interaction**: run commands, forward ports, list apps, and read logs
- **Coder Agents chats**: create chats, send messages, read transcripts and status, interrupt, archive, and list available models
- **User and system**: authenticated user details, organization memberships, tar uploads, and task reporting

The full, authoritative set of tools, including their names, descriptions, and
arguments, is defined in Coder's
[`toolsdk` package](../../codersdk/toolsdk/toolsdk.go). Refer to it for the
current list, since the available tools can change between releases.

## Available Prompts

The MCP server also exposes
[prompts](https://modelcontextprotocol.io/specification/2026-07-28/server/prompts)
for common Coder Agents chat workflows. Clients that support prompts surface
them for you to invoke, for example as slash commands:

- `coder_agents_delegate`: delegate a coding task to a Coder Agents chat and
  monitor it to completion
- `coder_agents_check`: check the status and recent activity of an existing
  Coder Agents chat

## Troubleshooting

### "Unauthorized" errors

- Verify your session token is valid and not expired
- Check that the MCP server experiment is enabled on your deployment
- Ensure your user has appropriate permissions for the requested operations

### Connection timeouts

- Verify your Coder deployment URL is correct and accessible
- Check network connectivity between your MCP client and the control plane
- Review the logs from `coderd`, the process that runs the control plane, for any errors

### OAuth2 authentication not working

- Ensure your Coder deployment has `CODER_OAUTH2_PROVIDER_ENABLE=true` set
- Verify your MCP client supports RFC 9728 Protected Resource Metadata
- Check that your browser can reach the Coder authorization endpoint

---

# Guides and tutorials

Source: https://coder.com/docs/tutorials

Here you can find a list of employee-written guides on Coder. These tutorials
are hosted on our [GitHub](https://github.com/coder/coder/) where you can leave
feedback or request new topics to be covered.

<children>
  This page is rendered on <https://coder.com/docs/tutorials>. Refer to the other documents in the `docs/tutorials/` directory for specific employee-written guides.
</children>

---

# Quickstart

Source: https://coder.com/docs/get-started

Follow this guide to get your first Coder development environment running in under 10&nbsp;minutes.
This guide covers the essential concepts and shows you how to create your first workspace and open it in your preferred editor.
This workspace includes a basic set of tools to edit most code bases.

## What you'll do

In this quickstart, you'll:

- ✅ Install the Coder control plane.
- ✅ Create a **template** (blueprint for dev environments).
- ✅ Launch a **workspace** (your actual dev environment).
- ✅ Connect from your favorite IDE.

## A 30-second metaphor for Coder

Before diving in, the following table breaks down the core concepts that power Coder,
explained through a cooking analogy:

| Component      | What It Is                                                                           | Real-World Analogy             |
|----------------|--------------------------------------------------------------------------------------|--------------------------------|
| **You**        | The engineer/developer/builder working                                               | The head chef cooking the meal |
| **Templates**  | A Terraform blueprint that defines your dev environment (OS, tools, resources)       | Recipe for a meal              |
| **Workspaces** | The actual running environment created from the template                             | The cooked meal                |
| **Users**      | A developer who launches the workspace from a template and does their work inside it | The people eating the meal     |

**Putting it Together:** Coder separates who _defines_ environments from who _uses_ them. Admins create and manage Templates, the recipes, while developers use those Templates to launch Workspaces, the meals.

## Prerequisites

- A machine with 2+ CPU cores and 4&nbsp;GB+ RAM (ideally a separate machine or VM, not your primary dev machine)
- Familiarity with running commands in the terminal
- 10&nbsp;minutes of your time

<details>
<summary>Why a separate machine?</summary>

Coder's value comes from remote development.
Hosting the control plane on a separate machine, such as a cloud VM, a spare desktop, or on-premises hardware, gives you and your team infrastructure that's more powerful, always-on, and reachable from anywhere, instead of tying your dev environment to your own laptop.

When you're ready to move past this tutorial, install the control plane on a separate machine and connect to it remotely.
Refer to the [Install guide](../install/index.md) for supported platforms and installation methods.

</details>

> [!TIP]
> If you use a coding agent like Claude Code, the [coder/skills](https://github.com/coder/skills) `setup` skill can train the coding agent on the following steps (install a container runtime, install Coder, create your first template, and launch a workspace).

## Step 1: Install a container runtime

Coder needs a Docker-compatible container runtime running on the host, such as
[Colima](https://colima.run), [Rancher Desktop](https://rancherdesktop.io),
[Podman](https://podman.io), or
[Docker Desktop](https://www.docker.com/products/docker-desktop/). If you
already have one installed and running, skip ahead to
[Step 2](#step-2-install-and-start-coder). Otherwise, follow the steps below to
install a free runtime quickly on your platform.

<div class="tabs">

### Linux

1. Install Docker Engine:

   ```sh
   curl -sSL https://get.docker.com | sh
   ```

   For more details, visit [Docker's docs on installing Docker on Linux](https://docs.docker.com/desktop/install/linux-install/).

1. Assign your user to the Docker group:

   ```sh
   sudo usermod -aG docker $USER
   ```

1. Run `newgrp` to activate the groups changes:

   ```sh
   newgrp docker
   ```

   You might need to log out of and back into your machine or restart your
   machine for changes to take effect.

1. Launch the Docker daemon:

   ```sh
   sudo systemctl start docker
   ```

### macOS

[Colima](https://colima.run) is a free, lightweight container runtime that
provides the Docker daemon on macOS without the overhead of Docker Desktop.

1. Install Colima and the Docker CLI with [Homebrew](https://brew.sh):

   ```sh
   brew install colima docker
   ```

1. Start Colima to launch the Docker daemon:

   ```sh
   colima start
   ```

1. Point `DOCKER_HOST` at the Colima socket so Coder can reach the daemon:

   ```sh
   export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
   ```

   Colima exposes its Docker socket at `~/.colima/default/docker.sock`, not `/var/run/docker.sock`, so Coder needs `DOCKER_HOST` to find it.
   Set it in the same terminal where you'll run `coder server` in the next step.
   To persist it across new terminals and restarts, add the `export` line to your shell's startup file, such as `~/.zshrc`, `~/.bashrc`, or `~/.config/fish/config.fish`.

### Windows

If you plan to use the built-in PostgreSQL database, ensure that the
[Visual C++ Runtime](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist#latest-microsoft-visual-c-redistributable-version)
is installed.

[Podman Desktop](https://podman-desktop.io) is a free GUI for the Podman container runtime.
Its onboarding installs and configures the required
Windows Subsystem for Linux (WSL2) or Hyper-V layer if it isn't already enabled.

1. Download and install [Podman Desktop](https://podman-desktop.io/downloads).

1. Follow the onboarding to configure Podman.

1. If you configured Podman to use WSL2, then you will need to do either
   upgrade WSL2 to version 2.5.1 or later
   (which uses [cgroups](https://wikipedia.org/wiki/Cgroups) v2 by default)
   or create a `.wslconfig` file in the `%USERPROFILE%` directory
   with the following contents

   ```txt
   [wsl2]
   kernelCommandLine=cgroup_no_v1=all
   ```

   This is not required for Podman with Hyper-V.

1. Open Podman Desktop and complete the onboarding to create and start a
   Podman machine.

   Podman Desktop enables Docker socket compatibility by default, so tools
   that expect the Docker daemon work without additional configuration.

</div>

## Step 2: Install and start Coder

Install the `coder` CLI to get started:

<div class="tabs">

### Linux/macOS

1. Install Coder:

   ```sh
   curl -fsSL https://coder.com/install.sh | sh
   ```

   - For standalone binaries, system packages, or other alternate installation
     methods, refer to the
     [latest release on GitHub](https://github.com/coder/coder/releases/latest).

1. Start Coder:

   ```sh
   coder server
   ```

### Windows

If you plan to use the built-in PostgreSQL database, ensure that the
[Visual C++ Runtime](https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist#latest-microsoft-visual-c-redistributable-version)
is installed.

1. Use the
   [`winget`](https://learn.microsoft.com/en-us/windows/package-manager/winget/#use-winget)
   package manager to install Coder:

   ```ps1
   winget install Coder.Coder
   ```

1. Start Coder:

   ```sh
   coder server
   ```

</div>

Coder will attempt to open the setup page in your browser. If it doesn't open
automatically, go to <http://localhost:3000>.

- If you get a browser warning similar to `Secure Site Not Available`, you can
  ignore the warning and continue to the setup page.

If your control plane is on a network or cloud device, or you are having trouble
viewing the page, locate the web UI URL in Coder logs in your terminal. It looks
like `https://<CUSTOM-STRING>.<TUNNEL>.try.coder.app`. It's one of the first
lines of output, so you might have to scroll up to find it.

This section includes some of the quicker ways to install Coder. For more detailed options, visit the [Install](../install/index.md) page.

## Step 3: Initial setup

1. Create your admin account:
   - Email: `your.email@example.com`
   - Password: Choose a strong password.

   You can also choose to **Continue with GitHub** instead of creating an admin
   account. Coder automatically grants admin permissions to the first user that signs in.

   ![Welcome to Coder - Create admin user](../images/screenshots/welcome-create-admin-user.png)

## Step 4: Create your first template and workspace

> [!TIP]
> If you use an AI coding assistant, the [coder-templates](https://github.com/coder/registry/blob/main/.agents/skills/coder-templates/SKILL.md) agent skill can guide you through creating and customizing templates with best practices built-in.

Templates define what's in your development environment. The template builder
guides you through creating one without writing any Terraform.

1. Coder opens the template builder after initial setup.
   To open it again later, select **Templates** > **New Template**.

1. Select the **Docker** base template from the list.

   > [!NOTE]
   > This template requires Docker to be running in the background, so make sure Docker is running.

1. Skip or configure any base template parameters, then select modules to add
   IDEs and tools to your template. For example, add **code-server** to get
   VS Code in the browser. You can skip module selection for now and add
   modules later.

1. On the final step, name your template:
   - **Name**: `my-docker-template`
   - **Display name** and **Description**: fill in as you like.

1. Select **Create Template**. Coder composes and validates the Terraform
   configuration, then creates your template.

   ![Template builder base selection step](../images/templatebuilder_01_bases.png)

**What just happened?**
The template builder selected a base infrastructure template, composed it with
any modules you chose, and generated a valid Terraform configuration. Coder
validated the configuration server-side, then created a reusable template in
your organization's template list. You and any teammates in the same
organization can now create workspaces from it.

<details>
<summary>What happens under the hood?</summary>

A Coder template is a [Terraform](https://developer.hashicorp.com/terraform/intro) configuration, and Coder is built on top of Terraform.
When you create a workspace from this template, a Coder [provisioner](../install/plan/architecture.md#provisionerd) runs a Terraform job from the template's configuration to build your environment.
For the Docker base template, that job starts a Docker container with the Coder agent pre-configured, along with any modules you selected.

To learn how Coder uses Terraform to provision and run workspaces, refer to the [architecture overview](../install/plan/architecture.md).

</details>

Now it's time to launch a workspace.

## Step 5: Launch your workspace

1. After the template is ready, select **+ Create Workspace**.

1. Give the workspace a name. If you need a suggestion, you can select the
   automatically generated name next to the **Need a suggestion?** label.

1. If the template has any
   [parameters](../admin/templates/extending-templates/parameters.md), fill
   them in. Parameters vary by template and the modules you selected in the
   builder.

1. Select **Create workspace**.

After a short wait (10-15&nbsp;seconds on most modern computers), Coder will start your new workspace:

![getting-started-workspace is running](../images/screenshots/workspace-running-with-topbar.png)_Workspace is running_

## Step 6: Connect your IDE

Each button in the workspace view is a different **agent app**.
The buttons in the UI reflect the modules you added in the template builder (such as code-server, Claude Code, or any of the JetBrains editors).
Select your preferred IDE from the list of agent apps.

This guide uses **VS Code Desktop**, which opens the workspace in the VS Code installed on your local machine, using the Coder extension.
To stay in the browser instead, select the browser-based VS Code option.
The remaining steps are similar for other IDEs and editors.

After VS Code loads the remote environment, you can select **Open Folder** to
explore directories in the Docker container or work on something new.

![Changing directories in VS Code](../images/screenshots/change-directory-vscode.png)

If you didn't clone an existing Git repository when you created your
workspace, you can clone it manually if you want:

1. Select **Clone Repository** and enter the repository URL.

   For example, to clone the Coder repo, enter
   `https://github.com/coder/coder.git`.

   Learn more about how to find the repository URL in the
   [GitHub documentation](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository).

2. Choose the folder to which VS Code should clone the repo. It will be in its
   own directory within this folder.

   Note that you cannot create a new parent directory in this step.

3. After VS Code completes the clone, select **Open** to open the directory.

4. You are now using VS Code in your Coder environment!

## What's next?

You now have:

- A control plane running locally.
- A template defining your environment.
- A workspace running that environment.
- IDE access to code remotely.

Now that you have your own workspace running, you can [customize your template](./customize-your-template/index.md) to fit your needs.

## Learn more

- [Try Coder Agents](../ai-coder/agents/getting-started.md), the chat
  interface and API for delegating development work to coding agents in your
  Coder deployment.

- [Read about managing Workspaces for your team](../user-guides/workspace-management.md)

- [Read about implementing monitoring tools for your Coder Deployment](../admin/monitoring/index.md)

## Troubleshooting

### Cannot connect to the Docker daemon

When creating a workspace from a Docker template, you may see an error like:

```txt
Error: Error pinging Docker server: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
```

This usually means a container runtime is either not installed or not running on the machine where Coder is running.
A runtime must be running before you create a workspace from a Docker-based template.

If the runtime is running but Coder still cannot connect, the daemon may expose its socket at a path other than `/var/run/docker.sock`.
This is common with Colima on macOS and with rootless Docker on Linux.
In that case, point Coder at the socket with the `DOCKER_HOST` environment variable, then restart the control plane.

<div class="tabs">

#### Linux

1. Install Docker, if you haven't already:

   ```sh
   curl -sSL https://get.docker.com | sh
   ```

1. Start the Docker daemon:

   ```sh
   sudo systemctl start docker
   ```

1. Assign your user to the `docker` group so Coder can access the daemon
   without root:

   ```sh
   sudo usermod -aG docker $USER
   newgrp docker
   ```

1. Confirm the group membership:

   ```console
   $ groups
   docker sudo users
   ```

#### macOS

1. If Colima is not installed, install it with [Homebrew](https://brew.sh):

   ```sh
   brew install colima docker
   ```

1. Start Colima to launch the Docker daemon:

   ```sh
   colima start
   ```

1. Verify that the daemon is reachable:

   ```sh
   docker ps
   ```

1. If `docker ps` works but Coder still cannot connect, point `DOCKER_HOST` at the Colima socket, then restart the control plane:

   ```sh
   export DOCKER_HOST="unix://${HOME}/.colima/default/docker.sock"
   ```

   To persist the setting across restarts, add that `export` line to your shell's startup file, such as `~/.zshrc`, `~/.bashrc`, or `~/.config/fish/config.fish`.

#### Windows

1. If Podman Desktop is not installed,
   [download and install it](https://podman-desktop.io/downloads).

1. Open Podman Desktop and verify that a Podman machine is running.

</div>

### Can't start `coder server`: Address already in use

```txt
Encountered an error running "coder server", see "coder server --help" for more information
error: configure http(s): listen tcp 127.0.0.1:3000: bind: address already in use
```

Another process is already listening on port 3000. Identify and stop it,
then start the control plane again.

<div class="tabs">

#### Linux

1. Stop the process:

   ```sh
   sudo systemctl stop coder
   ```

1. Start Coder:

   ```sh
   coder server
   ```

#### macOS

1. Identify the process using port 3000:

   ```sh
   lsof -i :3000
   ```

1. Stop the process using the PID from the previous command:

   ```sh
   kill <PID>
   ```

   If the process does not exit, force-kill it:

   ```sh
   kill -9 <PID>
   ```

1. Start Coder:

   ```sh
   coder server
   ```

#### Windows

1. Identify the process using port 3000 in PowerShell:

   ```ps1
   Get-NetTCPConnection -LocalPort 3000 | Select-Object OwningProcess
   ```

1. Stop the process using the PID from the previous command:

   ```ps1
   Stop-Process -Id <PID>
   ```

1. Start Coder:

   ```sh
   coder server
   ```

</div>

---

# Write a template from scratch

Source: https://coder.com/docs/tutorials/template-from-scratch

> [!TIP]
> If you want to create a template without writing Terraform, use the
> [template builder](../admin/templates/creating-templates.md#template-builder)
> instead. The builder guides you through selecting base infrastructure and
> adding modules through a visual interface.

A template is a common configuration that you use to deploy workspaces.

This tutorial teaches you how to create a template that provisions a workspace
as a Docker container with Ubuntu.

## Before you start

You'll need a computer or cloud computing instance with both
[Docker](https://docs.docker.com/get-docker/) and [Coder](../install/index.md)
installed on it.

## What's in a template

The main part of a Coder template is a [Terraform](https://terraform.io) `tf`
file. A Coder template often has other files to configure the other resources
that the template needs. In this tour you'll also create a `Dockerfile`.

Coder can provision all Terraform modules, resources, and properties. The Coder
server essentially runs a `terraform apply` every time a workspace is created,
started, or stopped.

> [!TIP]
> Haven't written Terraform before?
> Check out HashiCorp's [Getting Started Guides](https://developer.hashicorp.com/terraform/tutorials).

Here's a simplified diagram that shows the main parts of the template we'll
create:

![Template architecture](../images/templates/template-architecture.png)

## 1. Create template files

On your local computer, create a directory for your template and create the
`Dockerfile`. You will upload the files to your Coder instance later.

```sh
mkdir -p template-tour/build && cd $_
```

Enter content into a `Dockerfile` that starts with the
[official Ubuntu image](https://hub.docker.com/_/ubuntu/). In your editor, enter
and save the following text in `Dockerfile` then exit the editor:

```dockerfile
FROM ubuntu

RUN apt-get update \
    && apt-get install -y \
    sudo \
    curl \
    && rm -rf /var/lib/apt/lists/*

ARG USER=coder
RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
    && echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${USER} \
    && chmod 0440 /etc/sudoers.d/${USER}
USER ${USER}
WORKDIR /home/${USER}
```

`Dockerfile` adds a few things to the parent `ubuntu` image, which your template
needs later:

- It installs the `sudo` and `curl` packages.
- It adds a `coder` user, including a home directory.

## 2. Set up template providers

Edit the Terraform `main.tf` file to provision the workspace's resources.

Start by setting up the providers. At a minimum, we need the `coder` provider.
For this template, we also need the `docker` provider:

```tf
terraform {
  required_providers {
    coder = {
      source  = "coder/coder"
    }
    docker = {
      source  = "kreuzwerker/docker"
    }
  }
}

locals {
  username = data.coder_workspace_owner.me.name
}

data "coder_provisioner" "me" {
}

provider "docker" {
}

provider "coder" {
}

data "coder_workspace" "me" {
}

data "coder_workspace_owner" "me" {
}
```

Notice that the `provider` blocks for `coder` and `docker` are empty. In a more
practical template, you would add arguments to these blocks to configure the
providers, if needed.

The
[`coder_workspace`](https://registry.terraform.io/providers/coder/coder/latest/docs/data-sources/workspace)
data source provides details about the state of a workspace, such as its name,
owner, and so on. The data source also lets us know when a workspace is being
started or stopped. We'll use this information in later steps to:

- Set some environment variables based on the workspace owner.
- Manage ephemeral and persistent storage.

## 3. coder_agent

All templates need to create and run a
[Coder agent](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent).
This lets developers connect to their workspaces. The `coder_agent` resource
runs inside the compute aspect of your workspace, typically a VM or container.
In our case, it will run in Docker.

You do not need to have any open ports on the compute aspect, but the agent
needs `curl` access to the control plane.

Add this snippet after the last closing `}` in `main.tf` to create the agent:

```tf
resource "coder_agent" "main" {
  arch                   = data.coder_provisioner.me.arch
  os                     = "linux"
  startup_script         = <<-EOT
    set -e

    # install and start code-server
    curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
    /tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
  EOT

  env = {
    GIT_AUTHOR_NAME     = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
    GIT_AUTHOR_EMAIL    = "${data.coder_workspace_owner.me.email}"
    GIT_COMMITTER_NAME  = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name)
    GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}"
  }

  metadata {
    display_name = "CPU Usage"
    key          = "0_cpu_usage"
    script       = "coder stat cpu"
    interval     = 10
    timeout      = 1
  }

  metadata {
    display_name = "RAM Usage"
    key          = "1_ram_usage"
    script       = "coder stat mem"
    interval     = 10
    timeout      = 1
  }
}
```

Because Docker is running on the same machine as the control plane, there is no need to
authenticate `coder_agent`. But if your `coder_agent` is running on a remote
host, your template will need
[authentication credentials](../admin/external-auth/index.md).

This template's agent also runs a startup script, sets environment variables,
and provides metadata.

- [`startup script`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#startup_script)

  - Installs [code-server](https://coder.com/docs/code-server), a browser-based
    [VS Code](https://code.visualstudio.com/) app that runs in the workspace.

    We'll give users access to code-server through `coder_app` later.

- [`env` block](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent#env)

  - Sets environments variables for the workspace.

    We use the data source from `coder_workspace` to set the environment
    variables based on the workspace's owner. This way, the owner can make git
    commits immediately without any manual configuration.

- [`metadata`](../admin/templates/extending-templates/agent-metadata.md) blocks

  - Your template can use metadata to show information to the workspace owner
    Coder displays this metadata in the Coder dashboard.

    Our template has `metadata` blocks for CPU and RAM usage.

## 4. coder_app

A
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
resource lets a developer use an app from the workspace's Coder dashboard.

![Apps in a Coder workspace](../images/templates/workspace-apps.png)

This is commonly used for
[web IDEs](../user-guides/workspace-access/web-ides.md) such as
[code-server](https://coder.com/docs/code-server), RStudio, and JupyterLab.

We installed code-server in the `startup_script` argument. To add code-server to
the workspace, make it available in the workspace with a `coder_app` resource.
See [web IDEs](../user-guides/workspace-access/web-ides.md) for more examples:

```tf
resource "coder_app" "code-server" {
  agent_id     = coder_agent.main.id
  slug         = "code-server"
  display_name = "code-server"
  url          = "http://localhost:13337/?folder=/home/${local.username}"
  icon         = "/icon/code.svg"
  subdomain    = false
  share        = "owner"

  healthcheck {
    url       = "http://localhost:13337/healthz"
    interval  = 5
    threshold = 6
  }
}
```

You can also use a `coder_app` resource to link to external apps, such as links
to wikis or cloud consoles:

```tf
resource "coder_app" "coder-server-doc" {
  agent_id     = coder_agent.main.id
  icon         = "/emojis/1f4dd.png"
  slug         = "getting-started"
  url          = "https://coder.com/docs/code-server"
  external     = true
}
```

## 5. Persistent and ephemeral resources

Managing the lifecycle of template resources is important. We want to make sure
that workspaces use computing, storage, and other services efficiently.

We want our workspace's home directory to persist after the workspace is stopped
so that a developer can continue their work when they start the workspace again.

We do this in 2 parts:

- Our `docker_volume` resource uses the `lifecycle` block with the
  `ignore_changes = all` argument to prevent accidental deletions.
- To prevent Terraform from destroying persistent Docker volumes in case of a
  workspace name change, we use an immutable parameter, like
  `data.coder_workspace.me.id`.

Later, we use the Terraform
[count](https://developer.hashicorp.com/terraform/language/meta-arguments/count)
meta-argument to make sure that our Docker container is ephemeral.

```tf
resource "docker_volume" "home_volume" {
  name = "coder-${data.coder_workspace.me.id}-home"
  # Protect the volume from being deleted due to changes in attributes.
  lifecycle {
    ignore_changes = all
  }
}
```

For details, see
[Resource persistence](../admin/templates/extending-templates/resource-persistence.md).

## 6. Set up the Docker container

To set up our Docker container, our template has a `docker_image` resource that
uses `build/Dockerfile`, which we created earlier:

```tf
resource "docker_image" "main" {
  name = "coder-${data.coder_workspace.me.id}"
  build {
    context = "./build"
    build_args = {
      USER = local.username
    }
  }
  triggers = {
    dir_sha1 = sha1(join("", [for f in fileset(path.module, "build/*") : filesha1(f)]))
  }
}
```

Our `docker_container` resource uses `coder_workspace` `start_count` to start
and stop the Docker container:

```tf
resource "docker_container" "workspace" {
  count = data.coder_workspace.me.start_count
  image = docker_image.main.name
  # Uses lower() to avoid Docker restriction on container names.
  name = "coder-${data.coder_workspace_owner.me.name}-${lower(data.coder_workspace.me.name)}"
  # Hostname makes the shell more user friendly: coder@my-workspace:~$
  hostname = data.coder_workspace.me.name
  # Use the docker gateway if the access URL is 127.0.0.1
  entrypoint = ["sh", "-c", replace(coder_agent.main.init_script, "/localhost|127\\.0\\.0\\.1/", "host.docker.internal")]
  env = [
    "CODER_AGENT_TOKEN=${coder_agent.main.token}",
  ]
  host {
    host = "host.docker.internal"
    ip   = "host-gateway"
  }
  volumes {
    container_path = "/home/${local.username}"
    volume_name    = docker_volume.home_volume.name
    read_only      = false
  }
}
```

## 7. Create the template in Coder

Save `main.tf` and exit the editor.

Now that we've created the files for our template, we can add them to our Coder
deployment.

We can do this with the Coder CLI or the Coder dashboard. In this example, we'll
use the Coder CLI.

1. Log in to your Coder deployment from the CLI. This is where you need the URL
   for your deployment:

   ```console
   $ coder login https://coder.example.com
   Attempting to authenticate with config URL: 'https://coder.example.com'
   Open the following in your browser:

       https://coder.example.com/cli-auth

   > Paste your token here:
   ```

1. In your web browser, enter your credentials:

   ![Log in to your Coder deployment](../images/screenshots/coder-login.png)

1. Copy the session token to the clipboard:

   ![Copy session token](../images/templates/coder-session-token.png)

1. Paste it into the CLI:

   ```txt
   > Welcome to Coder, marc! You're authenticated.
   $
   ```

### Add the template files to Coder

Add your template files to your Coder deployment. You can upload the template
through the CLI, or through the Coder dashboard:

<div class="tabs">

#### CLI

1. Run `coder templates push` from the directory with your template files:

   ```console
   $ pwd
   /home/docs/template-tour
   $ coder templates push
   > Upload "."? (yes/no) yes
   ```

1. The Coder CLI tool gives progress information then prompts you to confirm:

   ```console
   > Confirm create? (yes/no) yes

   The template-tour template has been created! Developers can provision a workspace with this template using:

   coder create --template="template-tour" [workspace name]
   ```

1. In your web browser, log in to your Coder dashboard, select **Templates**.

1. Once the upload completes, select **Templates** from the top to deploy it to
   a new workspace.

   ![Your new template, ready to use](../images/templates/template-tour.png)

#### Dashboard

1. Create a `.zip` of the template files.

   - On Mac or Windows, highlight the files and then right click. A "compress"
     option is available through the right-click context menu.

   - To zip the files through the command line:

     ```sh
     zip templates.zip Dockerfile main.tf
     ```

1. Select **Templates** from the top of the Coder dashboard, then **Create
   Template**.
1. Select **Upload template**:

   ![Upload your first template](../images/templates/upload-create-your-first-template.png)

1. Drag the `.zip` file into the **Upload template** section and fill out the
   details, then select **Create template**.

   ![Upload the template files](../images/templates/upload-create-template-form.png)

1. Once the upload completes, select **Templates** from the top to deploy it to
   a new workspace.

   ![Your new template, ready to use](../images/templates/template-tour.png)

</div>

### Next steps

- [Setting up templates](../admin/templates/index.md)
- [Customizing templates](../admin/templates/extending-templates/index.md)
- [Troubleshooting template](../admin/templates/troubleshooting.md)

---

# Use Coder with an external database

Source: https://coder.com/docs/tutorials/external-database

## Recommendation

For production deployments, we recommend using an external
[PostgreSQL](https://www.postgresql.org/) database (version 13 or higher).

## Basic configuration

Before starting the control plane, prepare the database server by creating a role
and a database. Remember that the role must have access to the created database.

With `psql`:

```sql
CREATE ROLE coder LOGIN SUPERUSER PASSWORD 'secret42';
```

With `psql -U coder`:

```sql
CREATE DATABASE coder;
```

Coder configuration is defined via
[environment variables](../admin/setup/index.md). The database client requires
the connection string provided via the `CODER_PG_CONNECTION_URL` variable.

```sh
export CODER_PG_CONNECTION_URL="postgres://coder:secret42@localhost/coder?sslmode=disable"
```

## Custom schema

For installations with elevated security requirements, it's advised to use a
separate [schema](https://www.postgresql.org/docs/current/ddl-schemas.html)
instead of the public one.

With `psql -U coder`:

```sql
CREATE SCHEMA myschema;
```

Once the schema is created, you can list all schemas with `\dn`:

```txt
List of schemas
 Name      | Owner
-----------+----------
 myschema  | coder
 public    | postgres
(2 rows)
```

In this case the database client requires the modified connection string:

```sh
export CODER_PG_CONNECTION_URL="postgres://coder:secret42@localhost/coder?sslmode=disable&search_path=myschema"
```

The `search_path` parameter determines the order of schemas in which they are
visited while looking for a specific table. The first schema named in the search
path is called the current schema. By default `search_path` defines the
following schemas:

```sql
SHOW search_path;

search_path
--------------
 "$user", public
```

Using the `search_path` in the connection string corresponds to the following
`psql` command:

```sql
ALTER ROLE coder SET search_path = myschema;
```

## Troubleshooting

### `coder server` fails startup with "current_schema: converting NULL to string is unsupported"

Please make sure that the schema selected in the connection string
`...&search_path=myschema` exists and the role has granted permissions to access
it. The schema should be present on this listing:

```sh
psql -U coder -c '\dn'
```

---

# Image Management

Source: https://coder.com/docs/admin/templates/managing-templates/image-management

While Coder provides example
[container images](https://github.com/coder/images) for
workspaces, it's often best to create custom images that match the needs of
your users. This document serves as a guide to operational maturity with some
best practices around managing workspace images for Coder.

After following this tutorial, you'll accomplish the following:

1. Create a minimal base image.
2. Create golden images with standard tooling.
3. Create project-specific images for common use cases.
4. Let developers customize their own environment.

An image is just one of the many properties defined within the template.
Templates can pull images from a public image registry (e.g. Docker Hub) or an
internal one, thanks to Terraform. Each image reference below can be dropped
directly into a template's image variable or parameter.

## Create a minimal base image

While you may not use this directly in Coder templates, it's useful to have a
minimal base image as a small image that contains only the necessary
dependencies to work in your network and work with Coder. Here are some things
to consider:

- `curl`, `wget`, or `busybox` is required to download and run
  [the agent](../../../../provisionersdk/scripts/bootstrap_linux.sh)
- `git` is recommended so developers can clone repositories
- If the control plane is using a certificate from an internal certificate
  authority (CA), you'll need to add or mount these into your image
- Other generic utilities that will be required by all users, such as `ssh`,
  `docker`, `bash`, `jq`, and/or internal tooling
- Consider creating (and starting the container with) a non-root user

Examples:

- [`codercom/example-minimal:ubuntu`](https://github.com/coder/images/tree/main/images/minimal): only the necessary dependencies for a Coder workspace to bootstrap
- [`codercom/example-base:ubuntu`](https://github.com/coder/images/tree/main/images/base): a slightly more padded starting point with common utilities preinstalled

## Create golden images with standard tooling

Building on the base image, it's often practical to have a few golden images
that contain standard tooling for developers. These images should contain a
number of languages (e.g. Python, Java, TypeScript), IDEs (VS Code, JetBrains,
PyCharm), and other tools (e.g. `docker`). Unlike project-specific images
(which are also important), general purpose images are great for:

- **Scripting:** Developers may just want to hop in a Coder workspace to run
  basic scripts or queries.
- **Day 1 Onboarding:** New developers can quickly get started with a familiar
  environment without having to browse through (or create) an image
- **Basic Projects:** Developers can use these images for simple projects that
  don't require any specific tooling outside of the standard libraries. As the
  project gets more complex, its best to move to a project-specific image.
- **"Golden Path" Projects:** If your developer platform offers specific tech
  stacks and types of projects, the golden image can be a good starting point
  for those projects.

This is often referred to as a "sandbox" or "kitchen sink" image. Since large
multi-purpose container images can quickly become difficult to maintain, it's
important to keep the number of general-purpose images to a minimum (2-3 in
most cases) with a well-defined scope.

Examples:

- [`codercom/example-universal:ubuntu`](https://github.com/coder/images/tree/main/images/universal): a catch-all image with many languages and tools preinstalled. Runs as the `coder` user, so it works with Coder templates out of the box.
- [`mcr.microsoft.com/devcontainers/universal`](https://github.com/devcontainers/images/tree/main/src/universal): the Universal Dev Containers image

## Create project-specific images for common use cases

Beyond golden images, create images scoped to a specific project, language, or
use case (e.g., a Go backend, a Node.js frontend, or a data science stack).
These images stay smaller and faster to pull than one larger image that tries to install all dependencies.

Examples:

- [`codercom/example-golang:ubuntu`](https://github.com/coder/images/tree/main/images/golang),
  [`codercom/example-java:ubuntu`](https://github.com/coder/images/tree/main/images/java),
  [`codercom/example-node:ubuntu`](https://github.com/coder/images/tree/main/images/node):
  Coder's example language-specific images, all running as the `coder` user.
  Refer to [coder/images](https://github.com/coder/images) for the full list.
- [`codercom/oss-dogfood:latest`](https://github.com/coder/coder/tree/main/dogfood):
  the image Coder's own engineers use to develop Coder. A good reference for a
  project-specific image tailored to a specific team or monorepo setup.

## Let developers customize their own environment

Even with well-scoped images, developers will often need tooling that is
specific to their project or personal workflow. Instead of maintaining an
image for every combination, developers can layer their own customizations
on top of a smaller image:

- [Dev Containers](https://containers.dev): developers define their project's
  dependencies in a `devcontainer.json` in their Git repository, and Coder
  builds the environment on top of your base image. Visit
  [configure a template for Dev Containers](../../integrations/devcontainers/integration.md).
- [mise](https://mise.jdx.dev/): developers install and pin language runtimes
  and CLI tools at workspace startup without rebuilding the image. Visit the
  [install command-line tools guide](../../../get-started/customize-your-template/install-command-line-tools.md).

---

# Configure custom claims/scopes with Okta for group/role

Source: https://coder.com/docs/tutorials/configuring-okta

<div style="pad: 0px; margin: 0px;">
  <span style="vertical-align:middle;">Author: </span>
  <a href="https://github.com/Emyrk" style="text-decoration: none; color: inherit; margin-bottom: 0px;">
    <span style="vertical-align:middle;">Steven Masley</span>
  </a>
</div>
Updated: June, 2025

---

Okta is an identity provider that can be used for OpenID Connect (OIDC) Single
Sign On (SSO) on Coder.

To configure custom claims in Okta to support syncing roles and groups with
Coder, you must first have setup an Okta application with
[OIDC working with Coder](../admin/users/oidc-auth/index.md).
From here, we will add additional claims for Coder to use for syncing groups and
roles.

You may use a hybrid of the following approaches.

## (Easiest) Sync using Okta Groups

If the Coder roles & Coder groups can be inferred from
[Okta groups](https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-about-groups.htm),
Okta has a simple way to send over the groups as a `claim` in the `id_token`
payload.

In Okta, go to the application **Sign On** settings page.

**Applications** > **Select Application** > **General** > **Sign On**

In the **OpenID Connect ID Token** section, turn on **Groups Claim Type** and set
the **Claim name** to `groups`.
Optionally, configure a filter for which groups to be sent.

> [!IMPORTANT]
> If the user does not belong to any groups, the claim will not be sent.
> Make sure the user authenticating for testing is in at least one group.

![Okta OpenID Connect ID Token](../images/guides/okta/oidc_id_token.png)

Configure Coder to use these claims for group sync.
These claims are present in the `id_token`.
For more group sync configuration options, consult the [IDP sync documentation](../admin/users/idp-sync.md#group-sync).

```sh
# Add the 'groups' scope and include the 'offline_access' scope for refresh tokens
CODER_OIDC_SCOPES=openid,profile,email,offline_access,groups
# This name needs to match the "Claim name" in the configuration above.
CODER_OIDC_GROUP_FIELD=groups
```

> [!NOTE]
> The `offline_access` scope is required in Coder v2.23.0+ to prevent hourly session timeouts.

These groups can also be used to configure role syncing based on group
membership:

```sh
CODER_OIDC_SCOPES=openid,profile,email,offline_access,groups
# This name needs to match the "Claim name" in the configuration above.
CODER_OIDC_USER_ROLE_FIELD=groups
# Example configuration to map a group to some roles
CODER_OIDC_USER_ROLE_MAPPING='{"admin-group":["template-admin","user-admin"]}'
```

## (Easy) Mapping Okta profile attributes

If roles or groups cannot be completely inferred from Okta group memberships,
another option is to source them from a user's attributes.
The user attribute list can be found in **Directory** > **Profile Editor** > **User (default)**.

Coder can query an Okta profile for the application from the `/userinfo` OIDC endpoint.
To pass attributes to Coder, create the attribute in your application,
then add a mapping from the Okta profile to the application.

**Directory** > **Profile Editor** > {Your Application} > **Add Attribute**

Create the attribute for the roles, groups, or both. Make sure the attribute
is of type `string array`:

![Okta Add Attribute view](../images/guides/okta/add_attribute.png)

On the **Okta User to {Your Application}** tab, map a `roles` or `groups`
attribute you have configured to the application:

![Okta Add Claim view](../images/guides/okta/add_claim.png)

Configure using these new attributes in Coder:

```sh
# This must be set to false. Coder uses this endpoint to grab the attributes.
CODER_OIDC_IGNORE_USERINFO=false
# Include offline_access for refresh tokens
CODER_OIDC_SCOPES=openid,profile,email,offline_access
# Configure the group/role field using the attribute name in the application.
CODER_OIDC_USER_ROLE_FIELD=approles
# See our docs for mapping okta roles to coder roles.
CODER_OIDC_USER_ROLE_MAPPING='{"admin-group":["template-admin","user-admin"]}'

# If you added an attribute for groups, set that here.
# CODER_OIDC_GROUP_FIELD=...
```

> [!NOTE]
> The `offline_access` scope is required in Coder v2.23.0+ to prevent hourly session timeouts.

## (Advanced) Custom scopes to retrieve custom claims

Okta does not support setting custom scopes and claims in the default
authorization server used by your application.
If you require this functionality, you must create (or modify) an authorization server.

To see your custom authorization servers go to **Security** > **API**.
Note the `default` authorization server is not the authorization server your app is using.
You can configure this default authorization server, or create a new one specifically for your application.

Authorization servers also give more refined controls over things such as token/session lifetimes.

![Okta API view](../images/guides/okta/api_view.png)

To get custom claims working, map them to a custom scope.
Select the authorization server you wish to use (likely just using the default).

Go to **Scopes**, and **Add Scope**.
Feel free to create one for roles, groups, or both:

![Okta Add Scope view](../images/guides/okta/add_scope.png)

Create the claim to go with the said scope.
Go to **Claims**, then **Add Claim**.
Make sure to select **ID Token** for the token type.
The **Value** expression is up to you based on where you are sourcing the role information.
Configure it to only be a claim with the requested scope.
This is so if other applications exist, we do not send them information they do not care about:

![Okta Add Claim with Roles view](../images/guides/okta/add_claim_with_roles.png)

Now we have a custom scope and claim configured under an authorization server.
Configure Coder to use this:

```sh
# Grab this value from the Authorization Server > Settings > Issuer
# DO NOT USE the application issuer URL. Make sure to use the newly configured
# authorization server.
CODER_OIDC_ISSUER_URL=https://dev-12222860.okta.com/oauth2/default
# Add the new scope you just configured and offline_access for refresh tokens
CODER_OIDC_SCOPES=openid,profile,email,roles,offline_access
# Use the claim you just configured
CODER_OIDC_USER_ROLE_FIELD=roles
# See our docs for mapping okta roles to coder roles.
CODER_OIDC_USER_ROLE_MAPPING='{"admin-group":["template-admin","user-admin"]}'
```

> [!NOTE]
> The `offline_access` scope is required in Coder v2.23.0+ to prevent hourly session timeouts.

You can use the "Token Preview" page to verify it has been correctly configured
and verify the `roles` is in the payload.

![Okta Token Preview](../images/guides/okta/token_preview.png)

## Troubleshooting

### Users Are Logged Out Every Hour

**Symptoms**: Users experience session timeouts approximately every hour and must re-authenticate
**Cause**: Missing `offline_access` scope in `CODER_OIDC_SCOPES`
**Solution**:

1. Add `offline_access` to your `CODER_OIDC_SCOPES` configuration
1. Restart your Coder deployment
1. All existing users must logout and login once to receive refresh tokens

### Refresh Tokens Not Working After Configuration Change

**Symptoms**: Hourly timeouts, even after adding `offline_access`
**Cause**: Existing user sessions don't have refresh tokens stored
**Solution**: Users must logout and login again to get refresh tokens stored in the database

### Verify Refresh Token Configuration

To confirm that refresh tokens are working correctly:

1. Check that `offline_access` is included in your `CODER_OIDC_SCOPES`
1. Verify users can stay logged in beyond Okta's access token lifetime (typically one hour)
1. Monitor Coder logs for any OIDC refresh errors during token renewal

---

# Persistent shared workspaces with service accounts

Source: https://coder.com/docs/tutorials/persistent-shared-workspaces

> [!NOTE]
> This guide requires a
> [Premium license](https://coder.com/pricing#compare-plans) because service
> accounts are a Premium feature. For more details,
> [contact your account team](https://coder.com/contact).

This guide walks through setting up a long-lived workspace that is owned by a
service account and shared with a rotating set of users. Because no single
person owns the workspace, it persists across team changes and every user
authenticates as themselves.

This pattern is useful for any scenario where a workspace outlives the people
who use it:

- **On-call rotations** — Engineers share a workspace pre-loaded with runbooks,
  dashboards, and monitoring tools. Access rotates with the shift schedule.
- **Shared staging or QA** — A team workspace hosts a persistent staging
  environment. Testers and reviewers are added and removed as sprints change.
- **Pair programming** — A service-account-owned workspace gives two or more
  developers a shared environment without either one owning (and accidentally
  deleting) it.
- **Contractor onboarding** — An external team gets scoped access to a workspace
  for the duration of an engagement, then access is revoked.

The steps below use an **on-call SRE workspace** as a running example, but the
same commands apply to any of the scenarios above. Substitute the usernames,
group names, and template to match your use case.

## Prerequisites

- A running Coder deployment (v2.32+) with workspace sharing enabled. Sharing
  is on by default for OSS; Premium deployments may require
  [admin configuration](../user-guides/shared-workspaces.md#policies).
- The [Coder CLI](../install/index.md) installed and authenticated.
- An account with the `Owner` or `User Admin` role.
- [OIDC authentication](../admin/users/oidc-auth/index.md) configured so
  shared users log in with their corporate SSO identity. Configure
  [refresh tokens](../admin/users/oidc-auth/refresh-tokens.md) to prevent
  session timeouts during long work sessions.
- A [wildcard access URL](../admin/networking/wildcard-access-url.md) configured
  (e.g. `*.coder.example.com`) so that shared users can access workspace apps
  without a 404.
- (Recommended) [IdP Group Sync](../admin/users/idp-sync.md#group-sync)
  configured if your identity provider manages group membership for the teams
  that will share the workspace.

## 1. Create a service account

Create a dedicated service account that will own the shared workspace. Service
accounts are non-human accounts intended for automation and shared ownership.
Because no individual user owns the workspace, there are no personal
credentials to expose and the shared environment is not affected when any user
leaves the team or the organization.

```sh
# On-call example — substitute a name that fits your use case
coder users create \
  --username oncall-sre \
  --service-account
```

## 2. Generate an API token for the service account

Generate a long-lived API token so you can create and manage workspaces on
behalf of the service account:

```sh
coder tokens create \
  --user oncall-sre \
  --name oncall-automation \
  --lifetime 8760h
```

Store this token securely (e.g. in a secrets manager like Vault or AWS Secrets
Manager).

> [!IMPORTANT]
> Never distribute this token to end users. The token is for workspace
> administration only. Shared users authenticate as themselves and reach the
> workspace through sharing.

## 3. Create the workspace

Authenticate as the service account and create the workspace:

```sh
export CODER_SESSION_TOKEN="<token-from-step-2>"

coder create oncall-sre/oncall-workspace \
  --template your-oncall-template \
  --use-parameter-defaults \
  --yes
```

> [!TIP]
> Design a dedicated template for the workspace with the tools your team
> needs pre-installed (e.g. monitoring dashboards for on-call, test runners
> for QA). Set `subdomain = true` on workspace apps so that shared users can
> access web-based tools without a 404. See
> [Access workspace apps in shared workspaces](../user-guides/shared-workspaces.md#access-workspace-apps-in-shared-workspaces).

## 4. Share the workspace

Use `coder sharing share` to grant access to users who need the workspace:

```sh
coder sharing share oncall-sre/oncall-workspace --user alice
```

This gives `alice` the default `use` role, which allows connection via SSH and
workspace apps, starting and stopping the workspace, and viewing logs and stats.

To grant `admin` permissions (which includes all `use` permissions as well as renaming, updating, and inviting
others to join with the `use` role):

```sh
coder sharing share oncall-sre/oncall-workspace --user alice:admin
```

To share with multiple users at once:

```sh
coder sharing share oncall-sre/oncall-workspace --user alice:admin,bob
```

To share with an entire Coder group:

```sh
coder sharing share oncall-sre/oncall-workspace --group sre-oncall
```

> [!NOTE]
> Groups can be synced from your identity provider using
> [IdP Sync](../admin/users/idp-sync.md#group-sync). If your IdP already
> manages team membership, sharing with a group is the simplest approach.

## 5. Rotate access

When team membership changes, remove outgoing users and add incoming ones:

```sh
# Remove outgoing user
coder sharing remove oncall-sre/oncall-workspace --user alice

# Add incoming user
coder sharing share oncall-sre/oncall-workspace --user carol
```

> [!IMPORTANT]
> The workspace must be restarted for user removal to take effect.

Verify current sharing status at any time:

```sh
coder sharing status oncall-sre/oncall-workspace
```

## 6. Automate access changes (optional)

For use cases with frequent rotation (such as on-call shifts), you can integrate
the share/remove commands into external tooling like PagerDuty, Opsgenie, or a
cron job.

### Rotation script

```sh
#!/bin/bash
# rotate-access.sh
# Usage: ./rotate-access.sh <outgoing-user> <incoming-user>

WORKSPACE="oncall-sre/oncall-workspace"
OUTGOING="$1"
INCOMING="$2"

if [ -n "$OUTGOING" ]; then
  echo "Removing access for $OUTGOING..."
  coder sharing remove "$WORKSPACE" --user "$OUTGOING"
fi

echo "Granting access to $INCOMING..."
coder sharing share "$WORKSPACE" --user "$INCOMING"

echo "Restarting workspace to apply changes..."
coder restart "$WORKSPACE" --yes

echo "Current sharing status:"
coder sharing status "$WORKSPACE"
```

### Group-based rotation with IdP Sync

If your identity provider manages group membership (e.g. an `sre-oncall` group
in Okta or Azure AD), you can skip manual share/remove commands entirely:

1. Configure [Group Sync](../admin/users/idp-sync.md#group-sync) to
   synchronize the group from your IdP to Coder.

1. Share the workspace with the group once:

   ```sh
   coder sharing share oncall-sre/oncall-workspace --group sre-oncall
   ```

1. When your IdP rotates group membership, Coder group membership updates on
   next login. All current members have access; removed members lose access
   after a workspace restart.

<a id="finding-shared-workspaces"></a>

## Find shared workspaces

Shared users can find workspaces shared with them:

```sh
# List all shared workspaces you can access, including your own
coder list --search shared:true

# List workspaces shared with you
coder list --search shared_with_user:me

# List workspaces shared with a specific user
coder list --search shared_with_user:alice

# List workspaces shared with a specific group
coder list --search shared_with_group:sre-oncall
```

## Troubleshooting

### Shared user sees 404 on workspace apps

Workspace apps using path-based routing block non-owners by default. Configure a
[wildcard access URL](../admin/networking/wildcard-access-url.md) and set
`subdomain = true` on the workspace app in your template.

### Removed user still has access

Access removal requires a workspace restart. Run
`coder restart <workspace>` after removing a user or group.

### Group sync not updating membership

Group membership changes in your IdP are not reflected until the user logs out
and back in. Group sync runs at login time, not on a polling schedule. Check the
logs from `coderd`, the process that runs the control plane, with
`CODER_LOG_FILTER=".*userauth.*|.*groups returned.*"` for details. See
[Troubleshooting group sync](../admin/users/idp-sync.md#troubleshooting-grouproleorganization-sync)
for more information.

## Next steps

- [Shared Workspaces](../user-guides/shared-workspaces.md) — full reference
  for workspace sharing features and UI
- [IdP Sync](../admin/users/idp-sync.md) — group, role, and organization
  sync configuration
- [Configuring Okta](./configuring-okta.md) — Okta-specific OIDC setup with
  custom claims and scopes
- [Security Best Practices](./best-practices/security-best-practices.md) —
  deployment-wide security hardening
- [Sessions and Tokens](../admin/users/sessions-tokens.md) — API token
  management and scoping

---

# Federate a Google Cloud service account to AWS

Source: https://coder.com/docs/tutorials/gcp-to-aws

<div>
  <a href="https://github.com/ericpaulsen" style="text-decoration: none; color: inherit;">
    <span style="vertical-align:middle;">Eric Paulsen</span>
  </a>
</div>
January 4, 2024

---

This guide will walkthrough how to use a Google Cloud service account to
authenticate the Coder control plane to AWS and create an EC2 workspace. The
below steps assume your Coder control plane is running in Google Cloud and has
the relevant service account assigned.

For steps on assigning a service account to a resource like Coder, visit the
[Google documentation](https://cloud.google.com/iam/docs/attach-service-accounts#attaching-new-resource).

## 1. Get your Google service account OAuth Client ID

Navigate to the Google Cloud console, and select **IAM & Admin** > **Service
Accounts**. View the service account you want to use, and copy the **OAuth 2
Client ID** value shown on the right-hand side of the row.

Optionally: If you do not yet have a service account, use the
[Google IAM documentation on creating a service account](https://cloud.google.com/iam/docs/service-accounts-create) to create one.

## 2. Create AWS role

Create an AWS role that is configured for Web Identity Federation, with Google
as the identity provider, as shown below:

![AWS Create Role](../images/guides/gcp-to-aws/aws-create-role.png)

Once created, edit the **Trust Relationship** section to look like the
following:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "accounts.google.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "accounts.google.com:aud": "<enter-OAuth-client-ID-here"
                }
            }
        }
    ]
}
```

## 3. Assign permissions to the AWS role

In this example, Coder will need permissions to create the EC2 instance. Add the
following policy to the role:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "ec2:GetDefaultCreditSpecification",
                "ec2:DescribeIamInstanceProfileAssociations",
                "ec2:DescribeTags",
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceTypes",
                "ec2:CreateTags",
                "ec2:RunInstances",
                "ec2:DescribeInstanceCreditSpecifications",
                "ec2:DescribeImages",
                "ec2:ModifyDefaultCreditSpecification",
                "ec2:DescribeVolumes"
            ],
            "Resource": "*"
        },
        {
            "Sid": "CoderResources",
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstanceAttribute",
                "ec2:UnmonitorInstances",
                "ec2:TerminateInstances",
                "ec2:StartInstances",
                "ec2:StopInstances",
                "ec2:DeleteTags",
                "ec2:MonitorInstances",
                "ec2:CreateTags",
                "ec2:RunInstances",
                "ec2:ModifyInstanceAttribute",
                "ec2:ModifyInstanceCreditSpecification"
            ],
            "Resource": "arn:aws:ec2:*:*:instance/*",
            "Condition": {
                "StringEquals": {
                    "aws:ResourceTag/Coder_Provisioned": "true"
                }
            }
        }
    ]
}
```

## 4. Generate the identity token for the service account

Run the following `gcloud` command to generate the service account identity
token. This is a JWT token with a payload that includes the service account
email, audience, issuer, and expiration.

```console
gcloud auth print-identity-token --audiences=https://aws.amazon.com --impersonate-service-account 12345-compute@de
veloper.gserviceaccount.com  --include-email
```

> [!NOTE]
> Your `gcloud` client may needed elevated permissions to run this
> command.

## 5. Set identity token in Coder control plane

You will need to set the token created in the previous step on a location in the
Coder control plane. Follow the below steps for your specific deployment type:

### VM control plane

- Write the token to a file on the host, preferably inside the `/home/coder`
  directory:

```console
/home/coder/.aws/gcp-identity-token
```

### Kubernetes control plane

- Create the Kubernetes secret to house the token value:

```console
kubectl create secret generic gcp-identity-token -n coder --from-literal=token=<enter-token-here>
```

Make sure the secret is created inside the same namespace where Coder is
running.

- Mount the token file into the Coder pod using the values below:

```yaml
coder:
  volumes:
    - name: "gcp-identity-mount"
      secret:
        secretName: "gcp-identity-token"
  volumeMounts:
    - name: "gcp-identity-mount"
      mountPath: "/home/coder/.aws/gcp-identity-token"
      readOnly: true
```

## 6. Configure the AWS Terraform provider

Navigate to your EC2 workspace template in Coder, and configure the AWS provider
using the block below:

```tf
provider "aws" {
  assume_role_with_web_identity {
    # enter role ARN here - copy from AWS console
    role_arn = "arn:aws:iam::123456789:role/gcp-to-aws"
    # arbitrary value for logging
    session_name = "coder-session"
    # define location of token file on control plane here
    web_identity_token_file = "/home/coder/.aws/gcp-identity-token"
  }
}
```

This provider block is equivalent to running this `aws` CLI command:

```console
aws sts assume-role-with-web-identity \
  --role-arn arn:aws:iam::123456789:role/gcp-to-aws \
  --role-session-name coder-session \
  --web-identity-token xxx
```

You can run this command with the identity token string to validate or
troubleshoot the call to AWS.

---

# JFrog Artifactory integration

Source: https://coder.com/docs/admin/integrations/jfrog-artifactory

Use Coder and JFrog Artifactory together to secure your development environments
without disturbing your developers' existing workflows.

This guide will demonstrate how to use JFrog Artifactory as a package registry
within a workspace.

## Requirements

- A JFrog Artifactory instance
- 1:1 mapping of users in Coder to users in Artifactory by email address or
  username
- Repositories configured in Artifactory for each package manager you want to
  use

## Provisioner Authentication

The most straight-forward way to authenticate your template with Artifactory is
by using our official Coder [modules](https://registry.coder.com). We publish
two type of modules that automate the JFrog Artifactory and Coder integration.

1. [JFrog-OAuth](https://registry.coder.com/modules/jfrog-oauth)
1. [JFrog-Token](https://registry.coder.com/modules/jfrog-token)

### JFrog-OAuth

This module works with both JFrog SaaS (for example, `example.jfrog.io`) and self-hosted (on-premises) Artifactory.
It uses Coder's [external-auth](../external-auth/index.md) feature, so each user authenticates with Artifactory through an OAuth flow, and Coder issues a user-scoped access token to each workspace.

To set this up, follow these steps:

1. Create an application integration in Artifactory.
   Use `https://<CODER_URL>/external-auth/jfrog/callback` (your Coder deployment URL) as the callback URL and `applied-permissions/user` as the scope.

   **JFrog SaaS** (`example.jfrog.io`): Create the integration from the JFrog Platform UI as an administrator:

   1. Go to **Administration** > **General Management** > **Manage Integrations**, or open `https://<JFROG_URL>/ui/admin/configuration/integrations/application` directly.
   1. Select **New Integration**.
   1. Select **External Applications**.
   1. On the **Create New Application Integration** form, set **Application Name** to `Coder`, set **Application Type** to **Custom Integration**, and enter the callback URL.
   1. Select **Generate Client ID & Secret**.

   **Self-hosted (on-premises)**: First register an integration template in your Helm chart `values.yaml`, then create the application integration in the UI, and select that template as the **Application Type**.
   Replace `CODER_URL` with your Coder deployment URL:

   ```yaml
   artifactory:
     enabled: true
     frontend:
     extraEnvironmentVariables:
       - name: JF_FRONTEND_FEATURETOGGLER_ACCESSINTEGRATION
         value: "true"
     access:
     accessConfig:
       integrations-enabled: true
       integration-templates:
         - id: "1"
           name: "CODER"
           redirect-uri: "https://CODER_URL/external-auth/jfrog/callback"
           scope: "applied-permissions/user"
   ```

1. Add a new [external authentication](../external-auth/index.md) to Coder by setting these environment variables in a manner consistent with your Coder deployment.
   Replace `JFROG_URL` with your JFrog Artifactory base URL, and the client ID and secret with the values from step 1:

   ```dotenv
   # JFrog Artifactory External Auth
   CODER_EXTERNAL_AUTH_1_ID="jfrog"
   CODER_EXTERNAL_AUTH_1_TYPE="jfrog"
   CODER_EXTERNAL_AUTH_1_CLIENT_ID="YYYYYYYYYYYYYYY"
   CODER_EXTERNAL_AUTH_1_CLIENT_SECRET="XXXXXXXXXXXXXXXXXXX"
   CODER_EXTERNAL_AUTH_1_DISPLAY_NAME="JFrog Artifactory"
   CODER_EXTERNAL_AUTH_1_DISPLAY_ICON="/icon/jfrog.svg"
   CODER_EXTERNAL_AUTH_1_AUTH_URL="https://JFROG_URL/ui/authorization"
   CODER_EXTERNAL_AUTH_1_SCOPES="applied-permissions/user"
   ```

1. Create or edit a Coder template and use the [JFrog-OAuth](https://registry.coder.com/modules/jfrog-oauth) module to configure the integration:

   ```tf
   module "jfrog" {
     count          = data.coder_workspace.me.start_count
     source         = "registry.coder.com/coder/jfrog-oauth/coder"
     version        = "~> 1.0"
     agent_id       = coder_agent.example.id
     jfrog_url      = "https://example.jfrog.io"
     username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"

     package_managers = {
       npm    = ["npm", "@scoped:npm-scoped"]
       go     = ["go", "another-go-repo"]
       pypi   = ["pypi", "extra-index-pypi"]
       docker = ["example-docker-staging.jfrog.io", "example-docker-production.jfrog.io"]
     }
   }
   ```

### JFrog-Token

This module makes use of the [Artifactory terraform
provider](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs) and an admin-scoped token to create
user-scoped tokens for each user by matching their Coder email or username with
Artifactory. This can be used for both SaaS and self-hosted (on-premises)
Artifactory instances.

To set this up, follow these steps:

1. Get a JFrog access token from your Artifactory instance. The token must be an [admin token](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs#access-token) with scope `applied-permissions/admin`.

1. Create or edit a Coder template and use the [JFrog-Token](https://registry.coder.com/modules/jfrog-token) module to configure the integration and pass the admin token. It is recommended to store the token in a sensitive Terraform variable to prevent it from being displayed in plain text in the terraform state:

   ```tf
   variable "artifactory_access_token" {
     type      = string
     sensitive = true
   }

   module "jfrog" {
     source                   = "registry.coder.com/coder/jfrog-token/coder"
     version                  = "~> 1.0"
     agent_id                 = coder_agent.example.id
     jfrog_url                = "https://XXXX.jfrog.io"
     artifactory_access_token = var.artifactory_access_token
     package_managers = {
       npm    = ["npm", "@scoped:npm-scoped"]
       go     = ["go", "another-go-repo"]
       pypi   = ["pypi", "extra-index-pypi"]
       docker = ["example-docker-staging.jfrog.io", "example-docker-production.jfrog.io"]
     }
   }
   ```

> [!NOTE]
> The admin-level access token is used to provision user tokens and is never exposed to developers or stored in workspaces.

If you don't want to use the official modules, you can read through the [example template](../../../examples/jfrog/docker), which uses Docker as the underlying compute. The
same concepts apply to all compute types.

## Air-Gapped Deployments

See the [air-gapped deployments](../templates/extending-templates/modules.md#offline-installations) section for instructions on how to use Coder modules in an offline environment with Artifactory.

## Next Steps

- See the [full example Docker template](../../../examples/jfrog/docker).

- To serve extensions from your own VS Code Marketplace, check out
  [code-marketplace](https://github.com/coder/code-marketplace#artifactory-storage).

---

# Integrate Coder with Istio

Source: https://coder.com/docs/admin/integrations/istio

Use Istio service mesh for your Coder workspace traffic to implement access
controls, encrypt service-to-service communication, and gain visibility into
your workspace network patterns. This guide walks through the required steps to
configure the Istio service mesh for use with Coder.

While Istio is platform-independent, this guide assumes you are leveraging
Kubernetes. Ensure you have a running Kubernetes cluster with both Coder and
Istio installed, and that you have administrative access to configure both
systems. Once you have access to your Coder cluster, apply the following
manifest:

```yaml
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: tailscale-behind-istio-ingress
  namespace: istio-system
spec:
  configPatches:
    - applyTo: NETWORK_FILTER
      match:
        listener:
          filterChain:
            filter:
              name: envoy.filters.network.http_connection_manager
      patch:
        operation: MERGE
        value:
          typed_config:
            "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
            upgrade_configs:
              - upgrade_type: derp
```

---

# Island browser integration

Source: https://coder.com/docs/admin/integrations/island

<div>
  <a href="https://github.com/ericpaulsen" style="text-decoration: none; color: inherit;">
    <span style="vertical-align:middle;">Eric Paulsen</span>
  </a>
</div>
April 24, 2024

---

[Island](https://www.island.io/) is an enterprise-grade browser, offering a Chromium-based experience
similar to popular web browsers like Chrome and Edge. It includes built-in
security features for corporate applications and data, aiming to bridge the gap
between consumer-focused browsers and the security needs of the enterprise.

Coder natively integrates with Island's feature set, which include data
loss protection (DLP), application awareness, browser session recording, and
single sign-on (SSO). This guide intends to document these feature categories
and how they apply to your Coder deployment.

## General Configuration

### Create an Application Group for Coder

We recommend creating an Application Group specific to Coder in the Island
Management console. This Application Group object will be referenced when
creating browser policies.

[See the Island documentation for creating an Application Group](https://documentation.island.io/docs/create-and-configure-an-application-group-object).

## Advanced Data Loss Protection

Integrate Island's advanced data loss prevention (DLP) capabilities with
Coder's cloud development environment (CDE), enabling you to control the
"last mile" between developers' CDE and their local devices,
ensuring that sensitive IP remains in your centralized environment.

### Block cut, copy, paste, printing, screen share

1. [Create a Data Sandbox Profile](https://documentation.island.io/docs/create-and-configure-a-data-sandbox-profile).

1. Configure the following actions to allow/block (based on your security
   requirements).

   - Screenshot and Screen Share
   - Printing
   - Save Page
   - Clipboard Limitations

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the Data Sandbox Profile.

1. Define the Coder Application group as the Destination Object.

1. Define the Data Sandbox Profile as the Action in the Last Mile Protection
   section.

### Conditionally allow copy on Coder's CLI authentication page

1. [Create a URL Object](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) with the following configuration.

   - **Include**
   - **URL type**: Wildcard
   - **URL address**: `coder.example.com/cli-auth`
   - **Casing**: Insensitive

1. [Create a Data Sandbox Profile](https://documentation.island.io/docs/create-and-configure-a-data-sandbox-profile).

1. Configure action to allow copy/paste.

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the Data Sandbox Profile.

1. Define the URL Object you created as the Destination Object.

1. Define the Data Sandbox Profile as the Action in the Last Mile Protection
   section.

### Prevent file upload/download from the browser

1. Create a Protection Profiles for both upload/download.

   - [Upload documentation](https://documentation.island.io/docs/create-and-configure-an-upload-protection-profile)
   - [Download documentation](https://documentation.island.io/v1/docs/en/create-and-configure-a-download-protection-profile)

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the Protection Profiles.

1. Define the Coder Application group as the Destination Object.

1. Define the applicable Protection Profile as the Action in the Data Protection
   section.

### Scan files for sensitive data

1. [Create a Data Loss Prevention scanner](https://documentation.island.io/docs/create-a-data-loss-prevention-scanner).

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the DLP Scanner.

1. Define the Coder Application group as the Destination Object.

1. Define the DLP Scanner as the Action in the Data Protection section.

## Application Awareness and Boundaries

Ensure that Coder is only accessed through the Island browser, guaranteeing that
your browser-level DLP policies are always enforced, and developers can't
sidestep such policies simply by using another browser.

### Configure browser enforcement, conditional access policies

Create a conditional access policy for your configured identity provider.

Note that the configured IdP must be the same for both Coder and Island.

- [Azure Active Directory/Entra ID](https://documentation.island.io/docs/configure-browser-enforcement-for-island-with-azure-ad#create-and-apply-a-conditional-access-policy)
- [Okta](https://documentation.island.io/docs/configure-browser-enforcement-for-island-with-okta)
- [Google](https://documentation.island.io/docs/configure-browser-enforcement-for-island-with-google-enterprise)

## Browser Activity Logging

Govern and audit in-browser terminal and IDE sessions using Island, such as
screenshots, mouse clicks, and keystrokes.

### Activity Logging Module

1. [Create an Activity Logging Profile](https://documentation.island.io/docs/create-and-configure-an-activity-logging-profile). Supported browser
   events include:

   - Web Navigation
   - File Download
   - File Upload
   - Clipboard/Drag & Drop
   - Print
   - Save As
   - Screenshots
   - Mouse Clicks
   - Keystrokes

1. [Create a Policy Rule](https://documentation.island.io/docs/create-and-configure-a-policy-rule-general) to apply the Activity Logging Profile.

1. Define the Coder Application group as the Destination Object.

1. Define the Activity Logging Profile as the Action in the Security &
   Visibility section.

## Identity-aware logins (SSO)

Integrate Island's identity management system with Coder's
authentication mechanisms to enable identity-aware logins.

### Configure single sign-on (SSO) seamless authentication between Coder and Island

Configure the same identity provider (IdP) for both your Island and Coder
deployment. Upon initial login to the Island browser, the user's session
token will automatically be passed to Coder and authenticate their Coder
session.

---

# Define ImagePullSecrets for Coder workspaces

Source: https://coder.com/docs/tutorials/image-pull-secret

<div>
  <a href="https://github.com/ericpaulsen" style="text-decoration: none; color: inherit;">
    <span style="vertical-align:middle;">Eric Paulsen</span>
  </a>
</div>
January 12, 2024

---

Coder workspaces are commonly run as Kubernetes pods. When run inside of an
enterprise, the pod image is typically pulled from a private image registry.
This guide walks through creating an ImagePullSecret to use for authenticating
to your registry, and defining it in your workspace template.

## 1. Create Docker Config JSON File

Create a Docker configuration JSON file containing your registry credentials.
Replace `<your-registry>`, `<your-username>`, and `<your-password>` with your
actual Docker registry URL, username, and password.

```json
{
    "auths": {
        "<your-registry>": {
            "username": "<your-username>",
            "password": "<your-password>"
        }
    }
}
```

## 2. Create Kubernetes Secret

Run the below `kubectl` command in the K8s cluster where you intend to run your
Coder workspaces:

```console
kubectl create secret generic regcred \
  --from-file=.dockerconfigjson=<path-to-docker-config.json> \
  --type=kubernetes.io/dockerconfigjson \
  --namespace=<workspaces-namespace>
```

Inspect the secret to confirm its contents:

```console
kubectl get secret -n <workspaces-namespace> regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
```

The output should look similar to this:

```json
{
    "auths": {
        "your.private.registry.com": {
            "username": "ericpaulsen",
            "password": "xxxx",
            "auth": "c3R...zE2"
        }
    }
}
```

## 3. Define ImagePullSecret in Terraform template

With the ImagePullSecret now created, we can add the secret into the workspace
template. In the example below, we define the secret via the
`image_pull_secrets` argument. Note that this argument is nested at the same
level as the `container` argument:

```tf
resource "kubernetes_pod" "dev" {
  metadata {
    # this must be the same namespace where workspaces will be deployed
    namespace = "workspaces-namespace"
  }

  spec {
    image_pull_secrets {
      name = "regcred"
    }
    container {
      name  = "dev"
      image = "your-image:latest"
    }
  }
}
```

## 4. Push New Template Version

Update your template by running the following commands:

```console
coder login <access-url>
coder templates push <template-name>
```

---

# Configure Coder to connect to PostgreSQL using SSL

Source: https://coder.com/docs/tutorials/postgres-ssl

<div>
  <a href="https://github.com/ericpaulsen" style="text-decoration: none; color: inherit;">
    <span style="vertical-align:middle;">Eric Paulsen</span>
  </a>
</div>
February 24, 2024

---

Your organization may require connecting to the database instance over SSL. To
supply Coder with the appropriate certificates, and have it connect over SSL,
follow the steps below:

## Client verification (server verifies the client)

1. Create the certificate as a secret in your Kubernetes cluster, if not already
   present:

```sh
kubectl create secret tls postgres-certs -n coder --key="postgres.key" --cert="postgres.crt"
```

1. Define the secret volume and volumeMounts in the Helm chart:

```yaml
coder:
  volumes:
    - name: "pg-certs-mount"
      secret:
        secretName: "postgres-certs"
  volumeMounts:
    - name: "pg-certs-mount"
      mountPath: "$HOME/.postgresql"
      readOnly: true
```

1. Lastly, your PG connection URL will look like:

```sh
postgres://<user>:<password>@databasehost:<port>/<db-name>?sslmode=require&sslcert="$HOME/.postgresql/postgres.crt&sslkey=$HOME/.postgresql/postgres.key"
```

## Server verification (client verifies the server)

1. Download the CA certificate chain for your database instance, and create it
   as a secret in your Kubernetes cluster, if not already present:

```sh
kubectl create secret tls postgres-certs -n coder --key="postgres-root.key" --cert="postgres-root.crt"
```

1. Define the secret volume and volumeMounts in the Helm chart:

```yaml
coder:
  volumes:
    - name: "pg-certs-mount"
      secret:
        secretName: "postgres-certs"
  volumeMounts:
    - name: "pg-certs-mount"
      mountPath: "$HOME/.postgresql/postgres-root.crt"
      readOnly: true
```

1. Lastly, your PG connection URL will look like:

```sh
postgres://<user>:<password>@databasehost:<port>/<db-name>?sslmode=verify-full&sslrootcert="/home/coder/.postgresql/postgres-root.crt"
```

More information on connecting to PostgreSQL databases using certificates can
be found in the [PostgreSQL documentation](https://www.postgresql.org/docs/current/libpq-ssl.html#LIBPQ-SSL-CLIENTCERT).

---

# Federate Coder's control plane to Azure

Source: https://coder.com/docs/tutorials/azure-federation

<div>
  <a href="https://github.com/ericpaulsen" style="text-decoration: none; color: inherit;">
    <span style="vertical-align:middle;">Eric Paulsen</span>
  </a>
</div>
January 26, 2024

---

This guide will walkthrough how to authenticate a Coder Provisioner to Microsoft
Azure, using a Service Principal with a client certificate. You can use this
guide for authenticating Coder to Azure, regardless of where Coder is run,
either on-premise or in a non-Azure cloud. This method is one of several
[recommended by Terraform](https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs#authenticating-to-azure).

## Step 1: Generate Client Certificate & PKCS bundle

We'll need to create the certificate Coder will use for authentication. Run the
below command to generate a private key and self-signed certificate:

```console
openssl req -subj '/CN=myclientcertificate/O=MyCompany, Inc./ST=CA/C=US' \
  -new -newkey rsa:4096 -sha256 -days 730 -nodes -x509 -keyout client.key -out client.crt
```

Next, generate a `.pfx` file to be used by Coder's Provisioner to authenticate
the AzureRM provider:

```console
openssl pkcs12 -export -password pass:"Pa55w0rd123" -out client.pfx -inkey client.key -in client.crt
```

## Step 2: Create Azure Application & Service Principal

Navigate to the Azure portal, and into the Microsoft Entra ID section. Select
the App Registration blade, and register a new application. Fill in the
following fields:

- **Name**: this is a friendly identifier and can be anything (e.g. "Coder")
- **Supported Account Types**: - set to "Accounts in this organizational
  directory only (single-tenant)"

The **Redirect URI** field does not need to be set in this case. Take note of
the `Application (client) ID` and `Directory (tenant) ID` values, which will be
used by Coder.

## Step 3: Assign Client Certificate to the Azure Application

To upload the certificate we created in Step 1, select **Certificates &
secrets** on the left-hand side, and select **Upload Certificate**. Upload the
public key file, which is `service-principal.crt` from the example above.

## Step 4: Set Permissions on the Service Principal

Now that the Application is created in Microsoft Entra ID, we need to assign
permissions to the Service Principal so it can provision Azure resources for
Coder users. Navigate to the Subscriptions blade in the Azure Portal, select the
**Subscription > Access Control (IAM) > Add > Add role assignment**.

Set the **Role** that grants the appropriate permissions to create the Azure
resources you need for your Coder workspaces. `Contributor` will provide
Read/Write on all Subscription resources. For more information on the available
roles, see the
[Microsoft documentation](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles).

## Step 5: Configure Coder to use the Client Certificate

Now that the client certificate is uploaded to Azure, we need to mount the
certificate files into the Coder deployment. If running Coder on Kubernetes, you
will need to create the `.pfx` file as a Kubernetes secret, and mount it into
the Helm chart.

Run the below command to create the secret:

```console
kubectl create secret generic -n coder azure-client-cert-secret --from-file=client.pfx=/path/to/your/client.pfx
```

In addition, create secrets for each of the following values from your Azure
Application:

- Client ID
- Tenant ID
- Subscription ID
- Certificate password

Next, set the following values in Coder's Helm chart:

```yaml
coder:
  env:
    - name: ARM_CLIENT_ID
      valueFrom:
        secretKeyRef:
          key: id
          name: arm-client-id
    - name: ARM_CLIENT_CERTIFICATE_PATH
      value: /home/coder/az/
    - name: ARM_CLIENT_CERTIFICATE_PASSWORD
      valueFrom:
        secretKeyRef:
          key: password
          name: arm-client-cert-password
    - name: ARM_TENANT_ID
      valueFrom:
        secretKeyRef:
          key: id
          name: arm-tenant-id
    - name: ARM_SUBSCRIPTION_ID
      valueFrom:
        secretKeyRef:
          key: id
          name: arm-subscription-id
  volumes:
    - name: "azure-client-cert"
      secret:
        secretName: "azure-client-cert-secret"
  volumeMounts:
    - name: "azure-client-cert"
      mountPath: "/home/coder/az/"
      readOnly: true
```

Upgrade the Coder deployment using the following `helm` command:

```console
helm upgrade coder coder-v2/coder -n coder -f values.yaml
```

---

# Deploy Coder on Azure with an Application Gateway

Source: https://coder.com/docs/install/server/kubernetes/kubernetes-azure-app-gateway

In certain enterprise environments, the [Azure Application Gateway](https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-overview) is required.

These steps serve as a proof-of-concept example so that you can get Coder running with Kubernetes on Azure. Your deployment might require a separate Postgres server or signed certificates.

The Application Gateway supports:

- Websocket traffic (required for workspace connections)
- TLS termination

Refer to Microsoft's documentation on how to [enable application gateway ingress controller add-on for an existing AKS cluster with an existing application gateway](https://learn.microsoft.com/en-us/azure/application-gateway/tutorial-ingress-controller-add-on-existing).
The steps here follow the Microsoft tutorial for a Coder deployment.

## Deploy Coder on Azure with an Application Gateway

1. Create Azure resource group:

   ```sql
   az group create --name myResourceGroup --location eastus
   ```

1. Create AKS cluster:

   ```sql
   az aks create --name myCluster --resource-group myResourceGroup --network-plugin azure --enable-managed-identity --generate-ssh-keys
   ```

1. Create public IP:

   ```sql
   az network public-ip create --name myPublicIp --resource-group myResourceGroup --allocation-method Static --sku Standard
   ```

1. Create VNet and subnet:

   ```sql
   az network vnet create --name myVnet --resource-group myResourceGroup --address-prefix 10.0.0.0/16 --subnet-name mySubnet --subnet-prefix 10.0.0.0/24
   ```

1. Create Azure application gateway, attach VNet, subnet and public IP:

   ```sql
   az network application-gateway create --name myApplicationGateway --resource-group myResourceGroup --sku Standard_v2 --public-ip-address myPublicIp --vnet-name myVnet --subnet mySubnet --priority 100
   ```

1. Get app gateway ID:

   ```sql
   appgwId=$(az network application-gateway show --name myApplicationGateway --resource-group myResourceGroup -o tsv --query "id")
   ```

1. Enable app gateway ingress to AKS cluster:

   ```sql
   az aks enable-addons --name myCluster --resource-group myResourceGroup --addon ingress-appgw --appgw-id $appgwId
   ```

1. Get AKS node resource group:

   ```sql
   nodeResourceGroup=$(az aks show --name myCluster --resource-group myResourceGroup -o tsv --query "nodeResourceGroup")
   ```

1. Get AKS VNet name:

   ```sql
   aksVnetName=$(az network vnet list --resource-group $nodeResourceGroup -o tsv --query "[0].name")
   ```

1. Get AKS VNet ID:

   ```sql
   aksVnetId=$(az network vnet show --name $aksVnetName --resource-group $nodeResourceGroup -o tsv --query "id")
   ```

1. Peer VNet to AKS VNet:

   ```sql
   az network vnet peering create --name AppGWtoAKSVnetPeering --resource-group myResourceGroup --vnet-name myVnet --remote-vnet $aksVnetId --allow-vnet-access
   ```

1. Get app gateway VNet ID:

   ```sql
   appGWVnetId=$(az network vnet show --name myVnet --resource-group myResourceGroup -o tsv --query "id")
   ```

1. Peer AKS VNet to app gateway VNet:

   ```sql
   az network vnet peering create --name AKStoAppGWVnetPeering --resource-group $nodeResourceGroup --vnet-name $aksVnetName --remote-vnet $appGWVnetId --allow-vnet-access
   ```

1. Get AKS credentials:

   ```sql
   az aks get-credentials --name myCluster --resource-group myResourceGroup
   ```

1. Create Coder namespace:

   ```sh
   kubectl create ns coder
   ```

1. Deploy non-production PostgreSQL instance to AKS cluster:

   ```sh
   helm repo add bitnami https://charts.bitnami.com/bitnami
   helm install coder-db bitnami/postgresql \
   --set image.repository=bitnamilegacy/postgresql \
   --namespace coder \
   --set auth.username=coder \
   --set auth.password=coder \
   --set auth.database=coder \
   --set persistence.size=10Gi
   ```

1. Create the PostgreSQL secret:

   ```sh
   kubectl create secret generic coder-db-url -n coder --from-literal=url="postgres://coder:coder@coder-db-postgresql.coder.svc.cluster.local:5432/coder?sslmode=disable"
   ```

1. Get the application gateway's public IP address. Coder uses it as the access URL:

   ```sh
   az network public-ip show --name myPublicIp --resource-group myResourceGroup -o tsv --query "ipAddress"
   ```

1. Create a `values.yaml` file for the Coder Helm chart.
   Replace `<app-gateway-public-ip>` with the IP address from the previous step, or with a domain that resolves to it:

   ```yaml
   coder:
     env:
       - name: CODER_PG_CONNECTION_URL
         valueFrom:
           secretKeyRef:
             name: coder-db-url
             key: url
       - name: CODER_ACCESS_URL
         value: "http://<app-gateway-public-ip>"

     service:
       enable: true
       type: ClusterIP
       sessionAffinity: None
       externalTrafficPolicy: Cluster
       loadBalancerIP: ""
       annotations: {}
       httpNodePort: ""
       httpsNodePort: ""

     ingress:
       enable: true
       className: "azure-application-gateway"
       host: ""
       wildcardHost: ""
       annotations: {}
       tls:
         enable: false
         secretName: ""
         wildcardSecretName: ""
   ```

   The application gateway ingress controller that you enabled earlier watches for Ingress resources with the `azure-application-gateway` class and configures the gateway to route traffic to the Coder service.

1. Deploy Coder to AKS cluster:

   ```sh
   helm repo add coder-v2 https://helm.coder.com/v2
   helm install coder coder-v2/coder \
       --namespace coder \
       --values values.yaml \
       --version 2.25.2
   ```

1. Verify that the Ingress was assigned the application gateway's public IP address:

   ```sh
   kubectl get ingress -n coder
   ```

   After the `ADDRESS` column shows the IP address, go to your access URL in a browser to create the first Coder user.

1. When you no longer need the deployment, clean up Azure resources:

   ```sql
   az group delete --name myResourceGroup
   az group delete --name MC_myResourceGroup_myCluster_eastus
   ```

---

# Cloning Git Repositories

Source: https://coder.com/docs/tutorials/cloning-git-repositories

<div style="padding: 0px; margin: 0px;">
  <span style="vertical-align:middle;">Author: </span>
  <a href="https://github.com/BrunoQuaresma" style="text-decoration: none; color: inherit; margin-bottom: 0px;">
    <span style="vertical-align:middle;">Bruno Quaresma</span>
  </a>
</div>
August 06, 2024

---

When starting to work on a project, engineers usually need to clone a Git
repository. Even though this is often a quick step, it can be automated using
the [Coder Registry](https://registry.coder.com/) to make a seamless Git-first
workflow.

The first step to enable Coder to clone a repository is to provide
authorization. This can be achieved by using the Git provider, such as GitHub,
as an authentication method. If you don't know how to do that, we have written
documentation to help you:

- [GitHub](../admin/external-auth/index.md#github)
- [GitLab self-managed](../admin/external-auth/index.md#gitlab-self-managed)
- [Self-managed git providers](../admin/external-auth/index.md#self-managed-git-providers)

With the authentication in place, it is time to set up the template to use the
[Git Clone module](https://registry.coder.com/modules/git-clone) from the
[Coder Registry](https://registry.coder.com/) by adding it to our template's
Terraform configuration.

```tf
module "git-clone" {
  source   = "registry.coder.com/modules/git-clone/coder"
  version  = "1.0.12"
  agent_id = coder_agent.example.id
  url      = "https://github.com/coder/coder"
}
```

You can edit the template using an IDE or terminal of your preference, or by
going into the
[template editor UI](../admin/templates/creating-templates.md#web-ui).

You can also use
[template parameters](../admin/templates/extending-templates/parameters.md) to
customize the Git URL and make it dynamic for use cases where a template
supports multiple projects.

```tf
data "coder_parameter" "git_repo" {
  name         = "git_repo"
  display_name = "Git repository"
  default      = "https://github.com/coder/coder"
}

module "git-clone" {
  source   = "registry.coder.com/modules/git-clone/coder"
  version  = "1.0.12"
  agent_id = coder_agent.example.id
  url      = data.coder_parameter.git_repo.value
}
```

If you need more customization, you can read the
[Git Clone module](https://registry.coder.com/modules/git-clone) documentation
to learn more about the module.

Don't forget to build and publish the template changes before creating a new
workspace. You can check if the repository is cloned by accessing the workspace
terminal and listing the directories.

---

# Test and publish Coder templates through CI/CD

Source: https://coder.com/docs/tutorials/testing-templates

<div>
  <a href="https://github.com/matifali" style="text-decoration: none; color: inherit;">
    <span style="vertical-align:middle;">Muhammad Atif Ali</span>
  </a>
</div>
November 15, 2024

---

## Overview

This guide demonstrates how to test and publish Coder templates in a Continuous
Integration (CI) pipeline using the
[coder/setup-action](https://github.com/coder/setup-coder). This workflow
ensures your templates are validated, tested, and promoted seamlessly.

## Prerequisites

- Install and configure Coder CLI in your environment.
- Install Terraform CLI in your CI environment.
- Create a [headless user](../admin/users/headless-auth.md) with the
  [user roles and permissions](../admin/users/groups-roles.md#roles) to manage
  templates and run workspaces.

<a id="creating-the-headless-user"></a>

## Create the headless user

> [!WARNING]
> Creating users with `--login-type none` is deprecated.
> For [Premium](https://coder.com/pricing) deployments, use
> [service accounts](../admin/users/headless-auth.md) instead.
> For OSS deployments, use a regular account with password, GitHub, or OIDC
> authentication.

For Premium deployments, create a service account:

```sh
coder users create \
  --username machine-user \
  --service-account

coder tokens create --user machine-user --lifetime 8760h
# Copy the token and store it in a secret in your CI environment with the name `CODER_SESSION_TOKEN`
```

For OSS deployments, create a regular user:

```sh
coder users create \
  --username machine-user \
  --email machine-user@example.com \
  --login-type password

coder tokens create --user machine-user --lifetime 8760h
# Copy the token and store it in a secret in your CI environment with the name `CODER_SESSION_TOKEN`
```

## Example GitHub Action Workflow

This example workflow tests and publishes a template using GitHub Actions.

The workflow:

1. Validates the Terraform template.
1. Pushes the template to Coder without activating it.
1. Tests the template by creating a workspace.
1. Promotes the template version to active upon successful workspace creation.

### Workflow File

Save the following workflow file as `.github/workflows/publish-template.yaml` in
your repository:

```yaml
name: Test and Publish Coder Template

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  test-and-publish:
    runs-on: ubuntu-latest
    env:
      TEMPLATE_NAME: "my-template"
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Terraform
        uses: hashicorp/setup-terraform@v2
        with:
          terraform_version: latest

      - name: Set up Coder CLI
        uses: coder/setup-action@v1
        with:
          access_url: "https://coder.example.com"
          coder_session_token: ${{ secrets.CODER_SESSION_TOKEN }}

      - name: Validate Terraform template
        run: terraform validate

      - name: Get short commit SHA to use as template version name
        id: name
        run: echo "version_name=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"

      - name: Get latest commit title to use as template version description
        id: message
        run:
          echo "pr_title=$(git log --format=%s -n 1 ${{ github.sha }})" >>
          $GITHUB_OUTPUT

      - name: Push template to Coder
        run: |
          coder templates push $TEMPLATE_NAME --activate=false --name ${{ steps.name.outputs.version_name }} --message "${{ steps.message.outputs.pr_title }}" --yes

      - name: Create a test workspace and run some example commands
        run: |
          coder create -t $TEMPLATE_NAME --template-version ${{ steps.name.outputs.version_name }} test-${{ steps.name.outputs.version_name }} --yes
          # run some example commands
          coder ssh test-${{ steps.name.outputs.version_name }} -- make build

      - name: Delete the test workspace
        if: always()
        run: coder delete test-${{ steps.name.outputs.version_name }} --yes

      - name: Promote template version
        if: success()
        run: |
          coder template version promote --template=$TEMPLATE_NAME --template-version=${{ steps.name.outputs.version_name }}
```

---

# How to use Apache as a reverse-proxy with LetsEncrypt

Source: https://coder.com/docs/tutorials/reverse-proxy-apache

## Requirements

1. Start a Coder deployment and be sure to set the following
   [configuration values](../admin/setup/index.md):

   ```dotenv
   CODER_HTTP_ADDRESS=127.0.0.1:3000
   CODER_ACCESS_URL=https://coder.example.com
   CODER_WILDCARD_ACCESS_URL=*coder.example.com
   ```

   Throughout the guide, be sure to replace `coder.example.com` with the domain
   you intend to use with Coder.

2. Configure your DNS provider to point your coder.example.com and
   \*.coder.example.com to your server's public IP address.

   > For example, to use `coder.example.com` as your subdomain, configure
   > `coder.example.com` and `*.coder.example.com` to point to your server's
   > public ip. This can be done by adding A records in your DNS provider's
   > dashboard.

3. Install Apache (assuming you're on Debian/Ubuntu):

   ```sh
   sudo apt install apache2
   ```

4. Enable the following Apache modules:

   ```sh
   sudo a2enmod proxy
   sudo a2enmod proxy_http
   sudo a2enmod ssl
   sudo a2enmod rewrite
   ```

5. Stop Apache service and disable default site:

   ```sh
   sudo a2dissite 000-default.conf
   sudo systemctl stop apache2
   ```

## Install and configure LetsEncrypt Certbot

1. Install LetsEncrypt Certbot: Refer to the
   [CertBot documentation](https://certbot.eff.org/instructions?ws=apache&os=ubuntufocal&tab=wildcard).
   Be sure to pick the wildcard tab and select your DNS provider for
   instructions to install the necessary DNS plugin.

## Create DNS provider credentials

This example assumes you're using CloudFlare as your DNS provider. For other
providers, refer to the
[CertBot documentation](https://eff-certbot.readthedocs.io/en/stable/using.html#dns-plugins).

1. Create an API token for the DNS provider you're using: e.g.
   [CloudFlare](https://developers.cloudflare.com/fundamentals/api/get-started/create-token)
   with the following permissions:

   - Zone - DNS - Edit

2. Create a file in `.secrets/certbot/cloudflare.ini` with the following
   content:

   ```ini
   dns_cloudflare_api_token = YOUR_API_TOKEN
   ```

   ```sh
   mkdir -p ~/.secrets/certbot
   touch ~/.secrets/certbot/cloudflare.ini
   nano ~/.secrets/certbot/cloudflare.ini
   ```

3. Set the correct permissions:

   ```sh
   sudo chmod 600 ~/.secrets/certbot/cloudflare.ini
   ```

## Create the certificate

1. Create the wildcard certificate:

   ```sh
   sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini -d coder.example.com -d *.coder.example.com
   ```

## Configure Apache

This example assumes Coder is running locally on `127.0.0.1:3000` and that
you're using `coder.example.com` as your subdomain.

1. Create Apache configuration for Coder:

   ```sh
   sudo nano /etc/apache2/sites-available/coder.conf
   ```

2. Add the following content:

   ```apache
    # Redirect HTTP to HTTPS
    <VirtualHost *:80>
        ServerName coder.example.com
        ServerAlias *.coder.example.com
        Redirect permanent / https://coder.example.com/
    </VirtualHost>

    <VirtualHost *:443>
        ServerName coder.example.com
        ServerAlias *.coder.example.com
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        ProxyPass / http://127.0.0.1:3000/ upgrade=any # required for websockets
        ProxyPassReverse / http://127.0.0.1:3000/
        ProxyRequests Off
        ProxyPreserveHost On

        RewriteEngine On
        # Websockets are required for workspace connectivity
        RewriteCond %{HTTP:Connection} Upgrade [NC]
        RewriteCond %{HTTP:Upgrade} websocket [NC]
        RewriteRule /(.*) ws://127.0.0.1:3000/$1 [P,L]

        SSLCertificateFile /etc/letsencrypt/live/coder.example.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/coder.example.com/privkey.pem
    </VirtualHost>
   ```

   > Don't forget to change: `coder.example.com` by your (sub)domain

3. Enable the site:

   ```sh
   sudo a2ensite coder.conf
   ```

4. Restart Apache:

   ```sh
   sudo systemctl restart apache2
   ```

## Refresh certificates automatically

1. Create a new file in `/etc/cron.weekly`:

   ```sh
   sudo touch /etc/cron.weekly/certbot
   ```

2. Make it executable:

   ```sh
   sudo chmod +x /etc/cron.weekly/certbot
   ```

3. And add this code:

   ```sh
   #!/bin/sh
   sudo certbot renew -q
   ```

And that's it, you should now be able to access Coder at your sub(domain) e.g.
`https://coder.example.com`.

---

# Caddy

Source: https://coder.com/docs/tutorials/reverse-proxy-caddy

This is an example configuration of how to use Coder with
[caddy](https://caddyserver.com/docs). To use Caddy to generate TLS
certificates, you'll need a domain name that resolves to your Caddy server.

<a id="getting-started"></a>

## Get started

### With `docker compose`

1. [Install Docker](https://docs.docker.com/engine/install/) and
   [Docker Compose](https://docs.docker.com/compose/install/)

2. Create a `compose.yaml` file and add the following:

   ```yaml
   services:
   coder:
       image: ghcr.io/coder/coder:${CODER_VERSION:-latest}
       environment:
           CODER_PG_CONNECTION_URL: "postgresql://${POSTGRES_USER:-username}:${POSTGRES_PASSWORD:-password}@database/${POSTGRES_DB:-coder}?sslmode=disable"
           CODER_HTTP_ADDRESS: "0.0.0.0:7080"
           # You'll need to set CODER_ACCESS_URL to an IP or domain
           # that workspaces can reach. This cannot be localhost
           # or 127.0.0.1 for non-Docker templates!
           CODER_ACCESS_URL: "${CODER_ACCESS_URL}"
           # Optional) Enable wildcard apps/dashboard port forwarding
           CODER_WILDCARD_ACCESS_URL: "${CODER_WILDCARD_ACCESS_URL}"
           # If the coder user does not have write permissions on
           # the docker socket, you can uncomment the following
           # lines and set the group ID to one that has write
           # permissions on the docker socket.
           #group_add:
           #  - "998" # docker group on host
       volumes:
           - /var/run/docker.sock:/var/run/docker.sock
       depends_on:
           database:
           condition: service_healthy

   database:
       image: "postgres:17"
       ports:
           - "5432:5432"
       environment:
           POSTGRES_USER: ${POSTGRES_USER:-username} # The PostgreSQL user (useful to connect to the database)
           POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password} # The PostgreSQL password (useful to connect to the database)
           POSTGRES_DB: ${POSTGRES_DB:-coder} # The PostgreSQL default database (automatically created at first launch)
       volumes:
           - coder_data:/var/lib/postgresql/data # Use "docker volume rm coder_coder_data" to reset Coder
       healthcheck:
           test:
           [
               "CMD-SHELL",
               "pg_isready -U ${POSTGRES_USER:-username} -d ${POSTGRES_DB:-coder}",
           ]
           interval: 5s
           timeout: 5s
           retries: 5

   caddy:
       image: caddy:2.6.2
       ports:
           - "80:80"
           - "443:443"
           - "443:443/udp"
       volumes:
           - $PWD/Caddyfile:/etc/caddy/Caddyfile
           - caddy_data:/data
           - caddy_config:/config

   volumes:
       coder_data:
       caddy_data:
       caddy_config:
   ```

3. Create a `Caddyfile` and add the following:

   ```caddyfile
   {
       on_demand_tls {
           ask http://example.com
       }
   }

   coder.example.com, *.coder.example.com {
     reverse_proxy coder:7080
     tls {
           on_demand
         issuer acme {
            email email@example.com
         }
         }
   }
   ```

   Here;

   - `coder:7080` is the address of the Coder container on the Docker network.
   - `coder.example.com` is the domain name you're using for Coder.
   - `*.coder.example.com` is the domain name for wildcard apps, commonly used
     for [dashboard port forwarding](../admin/networking/port-forwarding.md).
     This is optional and can be removed.
   - `email@example.com`: Email to request certificates from LetsEncrypt/ZeroSSL
     (does not have to be Coder admin email)
   - `ask http://example.com`: Change this to a URL you control that
     validates the requested hostname before Caddy requests a certificate for
     it. See [this discussion](https://github.com/coder/coder/discussions/29079#discussioncomment-18462842)
     for a reference implementation.

4. Start Coder. Set `CODER_ACCESS_URL` and `CODER_WILDCARD_ACCESS_URL` to the
   domain you're using in your Caddyfile.

   ```sh
   export CODER_ACCESS_URL=https://coder.example.com
   export CODER_WILDCARD_ACCESS_URL=*.coder.example.com
   docker compose up -d # Run on startup
   ```

### Standalone

1. If you haven't already, [install Coder](../install/index.md)

2. Install [Caddy Server](https://caddyserver.com/docs/install)

3. Copy our sample `Caddyfile` and change the following values:

   ```caddyfile
   {
       on_demand_tls {
           ask http://example.com
       }
   }

   coder.example.com, *.coder.example.com {
     reverse_proxy coder:7080
   }
   ```

   > If you're installed Caddy as a system package, update the default Caddyfile
   > with `vim /etc/caddy/Caddyfile`

   - `email@example.com`: Email to request certificates from LetsEncrypt/ZeroSSL
     (does not have to be Coder admin email)
   - `coder.example.com`: Domain name you're using for Coder.
   - `*.coder.example.com`: Domain name for wildcard apps, commonly used for
     [dashboard port forwarding](../admin/networking/port-forwarding.md). This
     is optional and can be removed.
   - `localhost:3000`: Address Coder is running on. Modify this if you changed
     `CODER_HTTP_ADDRESS` in the Coder configuration.
   - `ask http://example.com`: Change this to a URL you control that
     validates the requested hostname before Caddy requests a certificate for
     it. See [this discussion](https://github.com/coder/coder/discussions/29079#discussioncomment-18462842)
     for a reference implementation.

4. [Configure Coder](../admin/setup/index.md) and change the following values:

   - `CODER_ACCESS_URL`: root domain (e.g. `https://coder.example.com`)
   - `CODER_WILDCARD_ACCESS_URL`: wildcard domain (e.g. `*.example.com`).

5. Start the Caddy server:

   If you're [keeping Caddy running](https://caddyserver.com/docs/running) via a
   system service:

   ```sh
   sudo systemctl restart caddy
   ```

   Or run a standalone server:

   ```sh
   caddy run
   ```

6. Optionally, use [ufw](https://wiki.ubuntu.com/UncomplicatedFirewall) or
   another firewall to disable external traffic outside of Caddy.

   ```sh
   # Check status of UncomplicatedFirewall
   sudo ufw status

   # Allow SSH
   sudo ufw allow 22

   # Allow HTTP, HTTPS (Caddy)
   sudo ufw allow 80
   sudo ufw allow 443

   # Deny direct access to Coder server
   sudo ufw deny 3000

   # Enable UncomplicatedFirewall
   sudo ufw enable
   ```

7. Navigate to your Coder URL! A TLS certificate should be auto-generated on
   your first visit.

<a id="generating-wildcard-certificates"></a>

## Generate wildcard certificates

By default, this configuration uses Caddy's [on-demand TLS](https://caddyserver.com/docs/caddyfile/options#on-demand-tls) to generate a certificate for each subdomain (e.g. `app1.coder.example.com`, `app2.coder.example.com`).
When users visit new subdomains, such as accessing [ports on a workspace](../admin/networking/port-forwarding.md), the request will take an additional 5-30&nbsp;seconds since a new certificate is being generated.

For production deployments, we recommend configuring Caddy to generate a
wildcard certificate, which requires an explicit DNS challenge and additional
Caddy modules.

1. Install a custom Caddy build that includes the
   [caddy-dns](https://github.com/caddy-dns) module for your DNS provider (e.g.
   CloudFlare, Route53).

   - Docker:
     [Build an custom Caddy image](https://github.com/docker-library/docs/tree/master/caddy#adding-custom-caddy-modules)
     with the module for your DNS provider. Be sure to reference the new image
     in the `compose.yaml`.

   - Standalone:
     [Download a custom Caddy build](https://caddyserver.com/download) with the
     module for your DNS provider. If you're using Debian/Ubuntu, you
     [can configure the Caddy package](https://caddyserver.com/docs/build#package-support-files-for-custom-builds-for-debianubunturaspbian)
     to use the new build.

2. Edit your `Caddyfile` and add the necessary credentials/API tokens to solve
   the DNS challenge for wildcard certificates.

   For example, for AWS Route53:

   ```diff
   tls {
   -  on_demand
   -  issuer acme {
   -      email email@example.com
   -  }

   +  dns route53 {
   +     max_retries 10
   +     aws_profile "real-profile"
   +     access_key_id "AKI..."
   +     secret_access_key "wJa..."
   +     token "TOKEN..."
   +     region "us-east-1"
   +  }
   }
   ```

   > Configuration reference from
   > [caddy-dns/route53](https://github.com/caddy-dns/route53).

   And for CloudFlare:

   Generate a
   [token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token)
   with the following permissions:

   - Zone:Zone:Edit

   ```diff
   tls {
   -  on_demand
   -  issuer acme {
   -      email email@example.com
   -  }

   +  dns cloudflare CLOUDFLARE_API_TOKEN
   }
   ```

   > Configuration reference from
   > [caddy-dns/cloudflare](https://github.com/caddy-dns/cloudflare).

---

# How to use NGINX as a reverse-proxy with LetsEncrypt

Source: https://coder.com/docs/tutorials/reverse-proxy-nginx

## Requirements

1. Start a Coder deployment and be sure to set the following
   [configuration values](../admin/setup/index.md):

   ```dotenv
   CODER_HTTP_ADDRESS=127.0.0.1:3000
   CODER_ACCESS_URL=https://coder.example.com
   CODER_WILDCARD_ACCESS_URL=*.coder.example.com
   ```

   Throughout the guide, be sure to replace `coder.example.com` with the domain
   you intend to use with Coder.

2. Configure your DNS provider to point your coder.example.com and
   \*.coder.example.com to your server's public IP address.

   > For example, to use `coder.example.com` as your subdomain, configure
   > `coder.example.com` and `*.coder.example.com` to point to your server's
   > public ip. This can be done by adding A records in your DNS provider's
   > dashboard.

3. Install NGINX (assuming you're on Debian/Ubuntu):

   ```sh
   sudo apt install nginx
   ```

4. Stop NGINX service:

   ```sh
   sudo systemctl stop nginx
   ```

<a id="adding-coder-deployment-subdomain"></a>

## Add the Coder deployment subdomain

This example assumes Coder is running locally on `127.0.0.1:3000` and that
you're using `coder.example.com` as your subdomain.

1. Create NGINX configuration for this app:

   ```sh
   sudo touch /etc/nginx/sites-available/coder.example.com
   ```

2. Activate this file:

   ```sh
   sudo ln -s /etc/nginx/sites-available/coder.example.com /etc/nginx/sites-enabled/coder.example.com
   ```

## Install and configure LetsEncrypt Certbot

1. Install LetsEncrypt Certbot: Refer to the
   [CertBot documentation](https://certbot.eff.org/instructions?ws=nginx&os=ubuntufocal&tab=wildcard).
   Be sure to pick the wildcard tab and select your DNS provider for
   instructions to install the necessary DNS plugin.

## Create DNS provider credentials

This example assumes you're using CloudFlare as your DNS provider. For other
providers, refer to the
[CertBot documentation](https://eff-certbot.readthedocs.io/en/stable/using.html#dns-plugins).

1. Create an API token for the DNS provider you're using: e.g.
   [CloudFlare](https://developers.cloudflare.com/fundamentals/api/get-started/create-token)
   with the following permissions:

   - Zone - DNS - Edit

2. Create a file in `.secrets/certbot/cloudflare.ini` with the following
   content:

   ```ini
   dns_cloudflare_api_token = YOUR_API_TOKEN
   ```

   ```sh
   mkdir -p ~/.secrets/certbot
   touch ~/.secrets/certbot/cloudflare.ini
   nano ~/.secrets/certbot/cloudflare.ini
   ```

3. Set the correct permissions:

   ```sh
   sudo chmod 600 ~/.secrets/certbot/cloudflare.ini
   ```

## Create the certificate

1. Create the wildcard certificate:

   ```sh
   sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials ~/.secrets/certbot/cloudflare.ini -d coder.example.com -d *.coder.example.com
   ```

## Configure nginx

1. Edit the file with:

   ```sh
   sudo nano /etc/nginx/sites-available/coder.example.com
   ```

2. Add the following content:

   ```nginx
   server {
       server_name coder.example.com *.coder.example.com;

       # HTTP configuration
       listen 80;
       listen [::]:80;

       # HTTP to HTTPS
       if ($scheme != "https") {
           return 301 https://$host$request_uri;
       }

       # HTTPS configuration
       listen [::]:443 ssl ipv6only=on;
       listen 443 ssl;
       ssl_certificate /etc/letsencrypt/live/coder.example.com/fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/coder.example.com/privkey.pem;

       location / {
           proxy_pass  http://127.0.0.1:3000; # Change this to your coder deployment port default is 3000
           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection upgrade;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_set_header X-Forwarded-Proto $scheme;
           add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
       }
   }
   ```

   > Don't forget to change: `coder.example.com` by your (sub)domain

3. Test the configuration:

   ```sh
   sudo nginx -t
   ```

## Refresh certificates automatically

1. Create a new file in `/etc/cron.weekly`:

   ```sh
   sudo touch /etc/cron.weekly/certbot
   ```

2. Make it executable:

   ```sh
   sudo chmod +x /etc/cron.weekly/certbot
   ```

3. And add this code:

   ```sh
   #!/bin/sh
   sudo certbot renew -q
   ```

## Restart NGINX

```sh
sudo systemctl restart nginx
```

And that's it, you should now be able to access Coder at your sub(domain) e.g.
`https://coder.example.com`.

---

# Pre-install JetBrains IDEs in your template

Source: https://coder.com/docs/admin/templates/extending-templates/jetbrains-preinstall

For a faster first time connection with JetBrains IDEs, pre-install the IDEs backend in your template.

> [!NOTE]
> This guide only talks about installing the IDEs backend. For a complete guide on setting up JetBrains Gateway with client IDEs, refer to the [JetBrains Gateway air-gapped guide](./jetbrains-airgapped.md).

## Install the Client Downloader

Install the JetBrains Client Downloader binary:

```sh
wget -O jetbrains-clients-downloader-linux-x86_64.tar.gz \
  'https://data.services.jetbrains.com/products/download?code=JCD&platform=linux_x86-64' && \
tar -xzvf jetbrains-clients-downloader-linux-x86_64.tar.gz
rm jetbrains-clients-downloader-linux-x86_64.tar.gz
```

## Install Gateway backend

```sh
mkdir ~/JetBrains
./jetbrains-clients-downloader-linux-x86_64-*/bin/jetbrains-clients-downloader --products-filter <product-code> --build-filter <build-number> --platforms-filter linux-x64 --download-backends ~/JetBrains
```

For example, to install the build `243.26053.27` of IntelliJ IDEA:

```sh
./jetbrains-clients-downloader-linux-x86_64-*/bin/jetbrains-clients-downloader --products-filter IU --build-filter 243.26053.27 --platforms-filter linux-x64 --download-backends ~/JetBrains
tar -xzvf ~/JetBrains/backends/IU/*.tar.gz -C ~/JetBrains/backends/IU
rm -rf ~/JetBrains/backends/IU/*.tar.gz
```

## Register the Gateway backend

Add the following command to your template's `startup_script`:

```sh
~/JetBrains/*/bin/remote-dev-server.sh registerBackendLocationForGateway
```

## Configure JetBrains Gateway Module

If you are using our [jetbrains-gateway](https://registry.coder.com/modules/coder/jetbrains-gateway) module, you can configure it by adding the following snippet to your template:

```tf
module "jetbrains_gateway" {
  count          = data.coder_workspace.me.start_count
  source         = "registry.coder.com/modules/jetbrains-gateway/coder"
  version        = "1.0.29"
  agent_id       = coder_agent.main.id
  folder         = "/home/coder/example"
  jetbrains_ides = ["IU"]
  default        = "IU"
  latest         = false
  jetbrains_ide_versions = {
    "IU" = {
      build_number = "251.25410.129"
      version      = "2025.1"
    }
  }
}

resource "coder_agent" "main" {
    ...
    startup_script = <<-EOF
    ~/JetBrains/*/bin/remote-dev-server.sh registerBackendLocationForGateway
    EOF
}
```

## Dockerfile example

If you are using Docker based workspaces, you can add the command to your Dockerfile:

```dockerfile
FROM codercom/example-base:ubuntu

# JetBrains IDE installation (configurable)
ARG IDE_CODE=IU
ARG IDE_VERSION=2025.1

# Fetch and install IDE dynamically
RUN mkdir -p ~/JetBrains \
    && IDE_URL=$(curl -s "https://data.services.jetbrains.com/products/releases?code=${IDE_CODE}&majorVersion=${IDE_VERSION}&latest=true" | jq -r ".${IDE_CODE}[0].downloads.linux.link") \
    && IDE_NAME=$(curl -s "https://data.services.jetbrains.com/products/releases?code=${IDE_CODE}&majorVersion=${IDE_VERSION}&latest=true" | jq -r ".${IDE_CODE}[0].name") \
    && echo "Installing ${IDE_NAME}..." \
    && wget -q ${IDE_URL} -P /tmp \
    && tar -xzf /tmp/$(basename ${IDE_URL}) -C ~/JetBrains \
    && rm -f /tmp/$(basename ${IDE_URL}) \
    && echo "${IDE_NAME} installed successfully"
```

## Next steps

- [Pre-install the Client IDEs](./jetbrains-airgapped.md#1-deploy-the-server-and-install-the-client-downloader)

---

# JetBrains IDEs in an air-gapped environment

Source: https://coder.com/docs/admin/templates/extending-templates/jetbrains-airgapped

In networks that restrict access to the internet, you will need to leverage the
JetBrains Client Installer to download and save the IDE clients locally. Please
see the
[JetBrains documentation for more information](https://www.jetbrains.com/help/idea/fully-offline-mode.html).

This page is an example that the Coder team used as a proof-of-concept (POC) of the JetBrains Gateway Offline Mode solution.

We used Ubuntu on a virtual machine to test the steps.
If you have a suggestion or encounter an issue, please
[file a GitHub issue](https://github.com/coder/coder/issues/new?title=request%28docs%29%3A+jetbrains-airgapped+-+request+title+here%0D%0A&labels=["community","docs"]&body=doc%3A+%5Bjetbrains-airgapped%5D%28https%3A%2F%2Fcoder.com%2Fdocs%2Fuser-guides%2Fworkspace-access%2Fjetbrains%2Fjetbrains-airgapped%29%0D%0A%0D%0Aplease+enter+your+request+here%0D%0A).

## 1. Deploy the server and install the Client Downloader

Install the JetBrains Client Downloader binary. Note that the server must be a Linux-based distribution:

```sh
wget -O jetbrains-clients-downloader-linux-x86_64.tar.gz \
  'https://data.services.jetbrains.com/products/download?code=JCD&platform=linux_x86-64' && \
tar -xzvf jetbrains-clients-downloader-linux-x86_64.tar.gz
```

## 2. Install backends and clients

JetBrains Gateway requires both a backend to be installed on the remote host
(your Coder workspace) and a client to be installed on your local machine. You
can host both on the server in this example.

See here for the full
[JetBrains product list and builds](https://data.services.jetbrains.com/products).
Below is the full list of supported `--platforms-filter` values:

```console
windows-x64, windows-aarch64, linux-x64, linux-aarch64, osx-x64, osx-aarch64
```

To install both backends and clients, you will need to run two commands.

### Backends

```sh
mkdir ~/backends
./jetbrains-clients-downloader-linux-x86_64-*/bin/jetbrains-clients-downloader --products-filter <product-code> --build-filter <build-number> --platforms-filter linux-x64,windows-x64,osx-x64 --download-backends ~/backends
```

### Clients

This is the same command as above, with the `--download-backends` flag removed.

```sh
mkdir ~/clients
./jetbrains-clients-downloader-linux-x86_64-*/bin/jetbrains-clients-downloader --products-filter <product-code> --build-filter <build-number> --platforms-filter linux-x64,windows-x64,osx-x64 ~/clients
```

We now have both clients and backends installed.

## 3. Install a web server

You will need to run a web server in order to serve requests to the backend and
client files. We installed `nginx` and setup an FQDN and routed all requests to
`/`. See below:

```console
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;

        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location / {
                root /home/ubuntu;
        }
}
```

Then, configure your DNS entry to point to the IP address of the server. For the
purposes of the POC, we did not configure TLS, although that is a supported
option.

## 4. Add Client Files

You will need to add the following files on your local machine in order for
Gateway to pull the backend and client from the server.

```sh
$ cat productsInfoUrl # a path to products.json that was generated by the backend's downloader (it could be http://, https://, or file://)

https://internal.site/backends/<PRODUCT_CODE>/products.json

$ cat clientDownloadUrl # a path for clients that you got from the clients' downloader (it could be http://, https://, or file://)

https://internal.site/clients/

$ cat jreDownloadUrl # a path for JBR that you got from the clients' downloader (it could be http://, https://, or file://)

https://internal.site/jre/

$ cat pgpPublicKeyUrl # a URL to the KEYS file that was downloaded with the clients builds.

https://internal.site/KEYS
```

The location of these files will depend upon your local operating system:

<div class="tabs">

### macOS

```console
# User-specific settings
/Users/UserName/Library/Application Support/JetBrains/RemoteDev
# System-wide settings
/Library/Application Support/JetBrains/RemoteDev/
```

### Linux

```console
# User-specific settings
$HOME/.config/JetBrains/RemoteDev
# System-wide settings
/etc/xdg/JetBrains/RemoteDev/
```

### Windows

```console
# User-specific settings
HKEY_CURRENT_USER registry
# System-wide settings
HKEY_LOCAL_MACHINE registry
```

Additionally, create a string for each setting with its appropriate value in
`SOFTWARE\JetBrains\RemoteDev`:

![JetBrains offline - Windows](../../../images/gateway/jetbrains-offline-windows.png)

</div>

## 5. Setup SSH connection with JetBrains Gateway

With the server now configured, you can now configure your local machine to use
Gateway. Here is the documentation to
[setup SSH config via the Coder CLI](../../../user-guides/workspace-access/index.md#configure-ssh).
On the Gateway side, follow our guide here until step 16.

Instead of downloading from jetbrains.com, we will point Gateway to our server
endpoint. Select `Installation options...` and select `Use download link`. Note
that the URL must explicitly reference the archive file:

![Offline Gateway](../../../images/gateway/offline-gateway.png)

Select **Download IDE and Connect**.
Gateway should now download the backend and clients from the server into your remote workspace and local machine, respectively.

## Next steps

- [Pre-install the JetBrains IDEs backend in your workspace](./jetbrains-preinstall.md)

---

# FAQs

Source: https://coder.com/docs/tutorials/faqs

Frequently asked questions on Coder OSS and licensed deployments. These FAQs
come from our community and customers, feel free to
[contribute to this page](https://github.com/coder/coder/edit/main/docs/tutorials/faqs.md).

For other community resources, see our
[GitHub discussions](https://github.com/coder/coder/discussions), or join our
[Discord server](https://discord.gg/coder).

## How do I add a Premium trial license?

Visit <https://coder.com/trial> or contact
[sales@coder.com](mailto:sales@coder.com?subject=License) to get a trial key.

<details>

<summary>You can add a license through the UI or CLI</summary>

<!-- copied from docs/admin/licensing/index.md -->

<div class="tabs">

### Coder UI

1. With an `Owner` account, go to **Admin settings** > **Deployment**.

1. Select **Licenses** from the sidebar, then **Add a license**:

   ![Add a license from the licenses screen](../images/admin/licenses/licenses-nolicense.png)

1. On the **Add a license** screen, drag your `.jwt` license file into the
   **Upload Your License** section, or paste your license in the
   **Paste Your License** text box, then select **Upload License**:

   ![Add a license screen](../images/admin/licenses/add-license-ui.png)

### Coder CLI

1. Ensure you have the [Coder CLI](../install/cli.md) installed.
1. Save your license key to disk and make note of the path.
1. Open a terminal.
1. Log in to your Coder deployment:

   ```sh
   coder login <access url>
   ```

1. Run `coder licenses add`:

   - For a `.jwt` license file:

     ```sh
     coder licenses add -f <path to your license key>
     ```

   - For a text string:

     ```sh
     coder licenses add -l 1f5...765
     ```

</div>

</details>

Visit the [licensing documentation](../install/prepare/licensing.md) for more
information about licenses.

## I'm experiencing networking issues, so want to disable Tailscale, STUN, Direct connections and force use of websocket

The primary developer use case is a local IDE connecting over SSH to a Coder
workspace.

Coder's networking stack has intelligence to attempt a peer-to-peer or
[Direct connection](../admin/networking/index.md#direct-connections) between the
local IDE and the workspace. However, this requires some additional protocols
like UDP and being able to reach a STUN server to echo the IP addresses of the
local IDE machine and workspace, for sharing using a Wireguard Coordination
Server. By default, Coder assumes Internet and attempts to reach Google's STUN
servers to perform this IP echo.

Operators experimenting with Coder may run into networking issues if UDP (which
STUN requires) or the STUN servers are unavailable, potentially resulting in
lengthy local IDE and SSH connection times as the Coder control plane attempts
to establish these direct connections.

Setting the following flags as shown disables this logic to simplify
troubleshooting.

| Flag                                                                                                | Value       | Meaning                               |
|-----------------------------------------------------------------------------------------------------|-------------|---------------------------------------|
| [`CODER_BLOCK_DIRECT`](../reference/cli/server/index.md#--block-direct-connections)                 | `true`      | Blocks direct connections             |
| [`CODER_DERP_SERVER_STUN_ADDRESSES`](../reference/cli/server/index.md#--derp-server-stun-addresses) | `"disable"` | Disables STUN                         |
| [`CODER_DERP_FORCE_WEBSOCKETS`](../reference/cli/server/index.md#--derp-force-websockets)           | `true`      | Forces websockets over Tailscale DERP |

## How do I configure NGINX as the reverse proxy in front of Coder?

[This tutorial](./reverse-proxy-nginx.md) in our docs explains in detail how to
configure NGINX with Coder so that our Tailscale Wireguard networking functions
properly.

## How do I hide some of the default icons in a workspace like VS Code Desktop, Terminal, SSH, Ports?

The visibility of Coder apps is configurable in the template. To change the
default (shows all), add this block inside the
[`coder_agent`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent)
of a template and configure as needed:

```tf
  display_apps {
    vscode = false
    vscode_insiders = false
    ssh_helper = false
    port_forwarding_helper = false
    web_terminal = true
  }
```

This example will hide all built-in
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
icons except the web terminal.

## I want to allow code-server to be accessible by other users in my deployment

We don't recommend that you share a web IDE, but if you need to, the following
deployment environment variable settings are required.

Set deployment (Kubernetes) to allow path app sharing:

```yaml
# allow authenticated users to access path-based workspace apps
- name: CODER_DANGEROUS_ALLOW_PATH_APP_SHARING
  value: "true"
# allow Coder owner roles to access path-based workspace apps
- name: CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS
  value: "true"
```

In the template, set
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app)
[`share`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app#share)
option to `authenticated` and when a workspace is built with this template, the
pretty globe shows up next to path-based `code-server`:

```tf
resource "coder_app" "code-server" {
  ...
  share        = "authenticated"
  ...
}
```

## I installed Coder and created a workspace but the icons do not load

An important concept to understand is that Coder creates workspaces which have
an agent that must be able to reach the control plane.

If the [`CODER_ACCESS_URL`](../admin/setup/index.md#access-url) is not
accessible from a workspace, the workspace may build, but the agent cannot reach
Coder, and thus the missing icons. e.g., Terminal, IDEs, Apps.

By default, `coder server` automatically creates an Internet-accessible
reverse proxy so that workspaces you create can reach the control plane.

If you are doing a standalone install, e.g., on a MacBook and want to build
workspaces in Docker Desktop, everything is self-contained and workspaces
(containers in Docker Desktop) can reach the control plane.

```sh
coder server --access-url http://localhost:3000 --address 0.0.0.0:3000
```

Even `coder server` which creates a reverse proxy, will let you use
<http://localhost> to access Coder from a browser.

## I updated a template, and an existing workspace based on that template fails to start

When updating a template, be aware of potential issues with input variables. For
example, if a template prompts users to choose options like a
[code-server](https://github.com/coder/code-server)
[VS Code](https://code.visualstudio.com/) IDE release, a
[container image](https://hub.docker.com/u/codercom), or a
[VS Code extension](https://marketplace.visualstudio.com/vscode), removing any
of these values can lead to existing workspaces failing to start. This issue
occurs because the Terraform state will not be in sync with the new template.

However, a lesser-known CLI sub-command,
[`coder update`](../reference/cli/update.md), can resolve this issue. This
command re-prompts users to re-enter the input variables, potentially saving the
workspace from a failed status.

```sh
coder update --always-prompt <workspace name>
```

## I'm running coder on a VM with systemd but latest release installed isn't showing up

Take, for example, a Coder deployment on a VM with a 2 shared vCPU systemd
service. In this scenario, it's necessary to reload the daemon and then restart
the Coder service. This prevents the `systemd` daemon from trying to reference
the previous Coder release service since the unit file has changed.

The following commands can be used to update Coder and refresh the service:

```sh
curl -fsSL https://coder.com/install.sh | sh
sudo systemctl daemon-reload
sudo systemctl restart coder.service
```

## I'm using the built-in Postgres database and forgot admin email I set up

1. Run the `coder server` command below to retrieve the `psql` connection URL
   which includes the database user and password.
2. `psql` into Postgres, and do a select query on the `users` table.
3. Restart the control plane, pull up the Coder UI and log in (you will still
   need your password)

```sh
coder server postgres-builtin-url
psql "postgres://coder@localhost:53737/coder?sslmode=disable&password=I2S...pTk"
```

## How to find out Coder's latest Terraform provider version?

[Coder is on the HashiCorp's Terraform registry](https://registry.terraform.io/providers/coder/coder/latest).
Check this frequently to make sure you are on the latest version.

Sometimes, the version may change and `resource` configurations will either
become deprecated or new ones will be added when you get warnings or errors
creating and pushing templates.

## How can I set up TLS for my deployment and not create a signed certificate?

Caddy is an easy-to-configure reverse proxy that also automatically creates
certificates from Let's Encrypt.
[Install docs here](https://caddyserver.com/docs/quick-starts/reverse-proxy) You
can start Caddy as a `systemd` service.

The Caddyfile configuration will appear like this where `127.0.0.1:3000` is your
`CODER_ACCESS_URL`:

```txt
coder.example.com {

  reverse_proxy 127.0.0.1:3000

  tls {

    issuer acme {
      email user@example.com
    }

  }
}
```

## I'm using Caddy as my reverse proxy in front of Coder. How do I set up a wildcard domain for port forwarding?

Caddy requires your DNS provider's credentials to create wildcard certificates.
This involves building the Caddy binary
[from source](https://github.com/caddyserver/caddy) with the DNS provider plugin
added. e.g.,
[Google Cloud DNS provider here](https://github.com/caddy-dns/googleclouddns)

To compile Caddy, the host running Coder requires Go. Once installed, replace
the existing Caddy binary in `usr/bin` and restart the Caddy service.

The updated Caddyfile configuration will look like this:

```txt
*.coder.example.com, coder.example.com {

  reverse_proxy 127.0.0.1:3000

  tls {
    issuer acme {
      email user@example.com
      dns googleclouddns {
        gcp_project my-gcp-project
      }
    }
  }

}
```

## Can I use local or remote Terraform Modules in Coder templates?

One way is to reference a Terraform module from a GitHub repo to avoid
duplication and then just extend it or pass template-specific
parameters/resources:

```tf
# template1/main.tf
module "central-coder-module" {
  source = "github.com/org/central-coder-module"
  myparam = "custom-for-template1"
}

resource "ebs_volume" "custom_template1_only_resource" {
}
```

```tf
# template2/main.tf
module "central-coder-module" {
  source = "github.com/org/central-coder-module"
  myparam = "custom-for-template2"
  myparam2 = "bar"
}

resource "aws_instance" "custom_template2_only_resource" {
}
```

Another way using local modules is to symlink the module directory inside the
template directory and then `tar` the template.

```sh
ln -s modules template_1/modules
tar -cvh -C ./template_1 | coder templates <push|create> -d - <name>
```

References:

- [Public GitHub Issue 6117](https://github.com/coder/coder/issues/6117)
- [Public GitHub Issue 5677](https://github.com/coder/coder/issues/5677)
- [Coder docs: Templates/Change Management](../admin/templates/managing-templates/change-management.md)

## Can I run Coder in an air-gapped or offline mode? (no Internet)?

Yes, Coder can be deployed in
[air-gapped or offline mode](../install/prepare/airgap.md).

Our product bundles with the Terraform binary so assume access to terraform.io
during installation. The docs outline rebuilding the Coder container with
Terraform built-in as well as any required Terraform providers.

Direct networking from local SSH to a Coder workspace needs a STUN server. Coder
defaults to Google's STUN servers, so you can either create your STUN server in
your network or disable and force all traffic through the control plane's DERP
proxy.

## Create a randomized computer_name for an Azure VM

Azure VMs have a 15 character limit for the `computer_name` which can lead to
duplicate name errors.

This code produces a hashed value that will be difficult to replicate.

```tf
locals {
  concatenated_string = "${data.coder_workspace.me.name}+${data.coder_workspace_owner.me.name}"
  hashed_string = md5(local.concatenated_string)
  truncated_hash = substr(local.hashed_string, 0, 16)
}
```

## Do you have example JetBrains Gateway templates?

In August 2023, JetBrains certified the Coder plugin signifying enhanced
stability and reliability.

The Coder plugin will appear in the Gateway UI when opened.

Selecting the most suitable template depends on how the deployment manages
JetBrains IDE versions. If downloading from
[jetbrains.com](https://www.jetbrains.com/remote-development/gateway/) is
acceptable, see the example templates below which specifies the product code,
IDE version and build number in the
[`coder_app`](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app#share)
resource.
This will present an icon in the workspace dashboard which, when selected, will look for a locally installed Gateway, and open it.
Alternatively, the IDE can be baked into the container image and manually open Gateway (or
IntelliJ which has Gateway built-in), using a session token to Coder and then
open the IDE.

## What options do I have for adding VS Code extensions into code-server, VS Code Desktop or Microsoft's Code Server?

Coder has an open-source project called
[`code-marketplace`](https://github.com/coder/code-marketplace) which is a
private VS Code extension marketplace. There is even integration with JFrog
Artifactory.

- [Blog post](https://coder.com/blog/running-a-private-vs-code-extension-marketplace)
- [OSS project](https://github.com/coder/code-marketplace)

You can also use Microsoft's code-server - which is like Coder's, but it
can connect to Microsoft's extension marketplace so Copilot and chat can be
retrieved there.

Another option is to use VS Code Desktop (local) and that connects to
Microsoft's marketplace.

## I want to run Docker for my workspaces but not install Docker Desktop

[Colima](https://github.com/abiosoft/colima) is a Docker Desktop alternative.

This example is meant for a users who want to try out Coder on a macOS device.

Install Colima and docker with:

```sh
brew install colima
brew install docker
```

Start Colima:

```sh
colima start
```

Start Colima with specific compute options:

```sh
colima start --cpu 4 --memory 8
```

Starting Colima on a M3 MacBook Pro:

```sh
colima start --arch x86_64  --cpu 4 --memory 8 --disk 10
```

Colima will show the path to the docker socket so we have a
[community template](https://github.com/sharkymark/v2-templates/tree/main/src/templates/docker/docker-code-server)
that prompts the Coder admin to enter the Docker socket as a Terraform variable.

## How to make a `coder_app` optional?

An example use case is the user should decide if they want a browser-based IDE
like code-server when creating the workspace.

1. Add a `coder_parameter` with type `bool` to ask the user if they want the
   code-server IDE

    ```tf
    data "coder_parameter" "code_server" {
        name        = "Do you want code-server in your workspace?"
        description = "Use VS Code in a browser."
        type        = "bool"
        default     = false
        mutable     = true
        icon        = "/icon/code.svg"
        order       = 6
    }
    ```

2. Add conditional logic to the `startup_script` to install and start
   code-server depending on the value of the added `coder_parameter`

    ```sh
    # install and start code-server, VS Code in a browser

    if [ ${data.coder_parameter.code_server.value} = true ]; then
    echo "🧑🏼‍💻 Downloading and installing the latest code-server IDE..."
    curl -fsSL https://code-server.dev/install.sh | sh
    code-server --auth none --port 13337 >/dev/null 2>&1 &
    fi
    ```

3. Add a Terraform meta-argument
   [`count`](https://developer.hashicorp.com/terraform/language/meta-arguments/count)
   in the `coder_app` resource so it will only create the resource if the
   `coder_parameter` is `true`

    ```tf
    # code-server
    resource "coder_app" "code-server" {
    count         = data.coder_parameter.code_server.value ? 1 : 0
    agent_id      = coder_agent.coder.id
    slug          = "code-server"
    display_name  = "code-server"
    icon          = "/icon/code.svg"
    url           = "http://localhost:13337?folder=/home/coder"
    subdomain = false
    share     = "owner"

    healthcheck {
        url       = "http://localhost:13337/healthz"
        interval  = 3
        threshold = 10
    }
    }
    ```

## Why am I getting this "remote host doesn't meet VS Code Server's prerequisites" error when opening up VSCode remote in a Linux environment?

![VS Code Server prerequisite](https://github.com/coder/coder/assets/10648092/150c5996-18b1-4fae-afd0-be2b386a3239)

It is because, more than likely, the supported OS of either the container image
or VM/VPS doesn't have the proper C libraries to run the VS Code Server. For
instance, Alpine is not supported at all. If so, you need to find a container
image or supported OS for the VS Code Server. For more information on OS
prerequisites for Linux, please look at the VSCode docs.
<https://code.visualstudio.com/docs/remote/linux#_local-linux-prerequisites>

## How can I resolve disconnects when connected to Coder via JetBrains Gateway?

If your JetBrains IDE is disconnected for a long period of time due to a network
change (for example turning off a VPN), you may find that the IDE will not
reconnect once the network is re-established (for example turning a VPN back
on). When this happens a persistent message will appear similar to the below:

```console
No internet connection. Changes in the document might be lost. Trying to reconnect…
```

To resolve this, add this entry to your SSH config file on your local machine:

```console
Host coder-jetbrains--*
  ServerAliveInterval 5
```

This will make SSH check that it can contact the server every five seconds.
If it fails to do so `ServerAliveCountMax` times (3 by default for a total of 15&nbsp;seconds) then it will close the connection which forces JetBrains to recreate the hung session.
You can tweak `ServerAliveInterval` and `ServerAliveCountMax` to increase or decrease the total timeout.

Note that the JetBrains Gateway configuration blocks for each host in your SSH
config file will be overwritten by the JetBrains Gateway client when it
re-authenticates to your Coder deployment so you must add the above config as a
separate block and not add it to any existing ones.

## How can I restrict inbound/outbound file transfers from Coder workspaces?

In certain environments, it is essential to keep confidential files within
workspaces and prevent users from uploading or downloading resources using tools
like `scp` or `rsync`.

To achieve this, template admins can use the environment variable
`CODER_AGENT_BLOCK_FILE_TRANSFER` to enable additional SSH command controls.
This variable allows the system to check if the executed application is on the
block list, which includes `scp`, `rsync`, `ftp`, and `nc`.

```tf
resource "docker_container" "workspace" {
  ...
  env = [
    "CODER_AGENT_TOKEN=${coder_agent.main.token}",
    "CODER_AGENT_BLOCK_FILE_TRANSFER=true",
    ...
  ]
}
```

### Important Notice

This control operates at the `ssh-exec` level or during `sftp` sessions. While
it can help prevent automated file transfers using the specified tools, users
can still SSH into the workspace and manually initiate file transfers. The
primary purpose of this feature is to warn and discourage users from downloading
confidential resources to their local machines.

Agent API capabilities, such as file operations performed by AI agents in
Coder Agents chat (including chat file uploads into the workspace), are not
affected by this setting because they do not go through the SSH transfer path.

For more advanced security needs, consider adopting an endpoint security
solution.

## How do I change the access URL for my control plane?

You may want to change the default domain that's used to access coder, i.e. `yourcompany.coder.com` and find yourself unfamiliar with the process.

To change the access URL associated with your control plane, you can edit any of the following variables:

- CLI using the `--access-url` flag
- YAML using the `accessURL` option
- or ENV using the `CODER_ACCESS_URL` environmental variable.

For example, if you're using an environment file to configure your control plane, you'll want to edit the file located at `/etc/coder.d/coder.env` and edit the following:

`CODER_ACCESS_URL=https://yourcompany.coder.com` to your new desired URL.

Then save your changes, and reload daemon-ctl using the following command:

`systemctl daemon-reload`

and restart the service using:

`systemctl restart coder`

After coder restarts, your changes should be applied and should reflect in the admin settings.

---

# Best practices

Source: https://coder.com/docs/tutorials/best-practices

Guides to help you make the most of your Coder experience.

<children></children>

---

# Organizations - best practices

Source: https://coder.com/docs/tutorials/best-practices/organizations

---

Coder [Organizations](../../admin/users/organizations.md) allow administrators
finer control over groups, templates, workspaces, and provisioners within their
Coder deployment.

Organizations allow multiple platform teams to offer templates and
infrastructure to their users instead of having them entirely managed in a
centralized fashion.

Each organization can have its own unique admin and users can belong to multiple
organizations, but every organization must have separate templates,
provisioners, groups, and workspaces.

On this best practice page, we cover some of the ways you can use Organizations
to make it easier to manage your groups smoothly.

## How Coder organizations work

Organizations are the hierarchical parent for templates, groups, and
provisioners. Every new organization must have separate templates, provisioners,
and groups.

![Organizations architecture](../../images/best-practice/organizations-architecture.png)

Users can belong to multiple organizations while templates and provisioners
cannot.

## When to use organizations

Organizations increase the maintenance overhead of a Coder deployment, so we
recommend that you only use them when necessary.

Use organizations when a separate group of users needs to manage their own
templates and underlying infrastructure. If a group of users already has a
separate, functional platform team willing to write templates or manage
clusters, organizations may be a good fit.

### Organization use case examples

Here are a few examples for a fictional organization called MegaCo. It is
deployed with Coder and has 1000 users in production. Today, MegaCo has a single
(default) organization and a central platform team but is evaluating whether to
use organizations for several use cases.

| **Use Case**                                                                         | **Description**                                                                                                                                                                                                                                                                                                                                                                   | **Good fit for organizations?**                                                                         |
|--------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------|
| Mergers and acquisitions                                                             | Raptix, a 180-person startup recently acquired by MegaCo, has an independent cloud account, platform team, and Terraform modules and pipelines for deploying their code. They want to use Coder.                                                                                                                                                                                  | ✅ Organizations                                                                                         |
| Independent cloud-native teams that manage their namespaces, images, and/or clusters | MegaCo has six teams responsible for their own dev, staging, and production Kubernetes clusters and frequently deploy & test their work with `kubectl` and `helm`.<br /><br />They wish to hook up Coder to their cluster so they can write and manage IDE templates for connecting to the cluster with their IDE                                                                 | ✅ Organizations                                                                                         |
| Java monolith                                                                        | MegaCo has identified that anyone developing the Java monolith is best served with a VM instead of a container/cloud-native environment.<br /><br />However, the Java team is supported by MegaCo's central platform team.                                                                                                                                                        | ❌ Use instead:<br />A separate template and/or groups                                                   |
| Off-shore contractors                                                                | MegaCo employs off-shore contractors but has not onboarded them onto Coder due to privacy concerns, data sovereignty rules, and latency considerations.<br /><br />They considered a minimal, localized second deployment of Coder, but decided against it due to maintenance overhead.                                                                                           | ✅ Organizations + Workspace Proxies                                                                     |
| Dev teams                                                                            | Dev teams often need to bring their requirements for dev environments, such as specific repositories and tools                                                                                                                                                                                                                                                                    | ❌ Use instead:<br />Parameters, dev containers, and/or groups                                           |
| ML Platform Team & ML Developers                                                     | MegaCo's data platform team maintains a homegrown "MLBox" product for data environments with a GPU, Jupyter, etc.<br /><br />This team is interested in migrating to Coder for improved cost-saving and auditing of environments, but they need to hook up their own cluster and cloud accounts. They also want their templates only to be accessible to a specific set of users. | ✅ Organizations                                                                                         |
| Supporting developers in various regions                                             | MegaCo's central platform team supports developers connecting from the East Coast, the West Coast, and Australia. These developers are working on the same projects but need low-latency access to their environments.                                                                                                                                                            | ❌ Use instead:<br />Provisioners and workspace proxies to support multiple regions on a single template |

## How to migrate to organizations

Since templates and workspaces cannot be moved nor can they belong to multiple
organizations, we recommend that you deprecate your template
[through the API](../../reference/api/templates.md#update-template-settings-by-id)
or [through the Coder CLI](../../reference/cli/templates/edit.md#--deprecated).
When a template is deprecated, the admin prevents new workspaces from being
created and developers are notified with a deprecation message which can link to
an external wiki page on migration instructions.

Users can use a file transfer tool such as
[rsync](https://linux.die.net/man/1/rsync) to migrate their files from one
workspace to another.

## Provisioner Isolation and Zero Trust

In the organizations model, provisioners run in a separate
cluster/infrastructure and have an isolated key to authenticate back with Coder.
The provisioners have access to separate cloud resources that the control plane
cannot access. Instead, the control plane sends simple "provisioner jobs" to the
provisioner and the provisioner is responsible for executing the Terraform.

There are planned improvements to the troubleshooting provisioners process.
Follow this GitHub issue for more details:

- [coder/coder#15192](https://github.com/coder/coder/issues/15192)

## Identity Provider (SSO) Sync

While the Coder UI or API can be used to assign specific users to organizations,
this is discouraged. Instead, we recommend syncing the state from your identity
provider such as Okta. A single claim from the identity provider (like
`memberOf`) can be used to sync site-wide roles, organizations, groups, and
organization roles.

Regex filters and mapping can be configured to ensure the proper resources are
allocated in Coder. Learn more about [IDP sync](../../admin/users/idp-sync.md).

## Custom Roles

Custom roles are organization-scoped and can be used to limit access controls
within an organization. Custom roles can be applied to the default organization.

Some examples of custom roles that can be created:

### Provisioner Admin

- The user can deploy provisioners but not manage templates. This may be useful
  if automation is used to create and update templates in the organization.

### Template Editor

- Inverse of provisioner admin: User can manage templates but not deploy
  provisioners. This may be useful if the provisioner and template are deployed
  via automation and users are allowed to edit them.

### Template Pusher

- A system account that can push new templates from a git repo but cannot manage
  users or delete templates.

We’re interested in identifying new use cases for custom roles. Please
[create a GitHub issue](https://github.com/coder/internal/issues/new?title=request%28orgs%29%3A+request+title+here&labels=["customer-feedback"]&body=please+enter+your+request+here)
with your suggestion or request.

<a id="managing-organizations-at-scale"></a>

## Manage organizations at scale

Using ClickOps to onboard new organizations, set quotas, and SSO sync can be
cumbersome, especially if you want to "seed" organizations with provisioners and
starter templates.

We suggest using the coderd Terraform provider to manage organizations at scale.
Documentation and examples for the Organization and Group Sync resources is available
at https://registry.terraform.io/providers/coder/coderd/latest/docs. Feature requests
for additional functionality can be created at https://github.com/coder/terraform-provider-coderd/issues.

---

# Scale Coder

Source: https://coder.com/docs/tutorials/best-practices/scale-coder

This best practice guide helps you prepare a Coder deployment that you can
scale up to a high-scale deployment as use grows, and keep it operating smoothly with a
high number of active users and workspaces.

## Observability

Observability is one of the most important aspects to a scalable Coder deployment.
When you have visibility into performance and usage metrics, you can make informed
decisions about what changes you should make.

[Monitor your Coder deployment](../../admin/monitoring/index.md) with log output
and metrics to identify potential bottlenecks before they negatively affect the
end-user experience and measure the effects of modifications you make to your
deployment.

- Log output
  - Capture log output from from control plane instances and external provisioner daemons
  and store them in a searchable log store like Loki, CloudWatch logs, or other tools.
  - Retain logs for a minimum of thirty days, ideally ninety days.
  This allows you investigate when anomalous behaviors began.

- Metrics
  - Capture infrastructure metrics like CPU, memory, open files, and network I/O for all
  control plane, external provisioner daemon, workspace proxy, and PostgreSQL instances.
  - Capture control plane and external provisioner daemon metrics
  [via Prometheus](#how-to-capture-control-plane-metrics-with-prometheus).

Retain metric time series for at least six months. This allows you to see
performance trends relative to user growth.

For a more comprehensive overview, integrate metrics with an observability
dashboard like [Grafana](../../admin/monitoring/index.md).

### Observability key metrics

Configure alerting based on these metrics to ensure you surface problems before
they affect the end-user experience.

- CPU and Memory Utilization
  - Monitor the utilization as a fraction of the available resources on the instance.

     Utilization will vary with use throughout the course of a day, week, and longer timelines.
     Monitor trends and pay special attention to the daily and weekly peak utilization.
     Use long-term trends to plan infrastructure upgrades.

- Tail latency of Coder API requests
  - High tail latency can indicate the control plane or the PostgreSQL database is underprovisioned
  for the load.
  - Use the `coderd_api_request_latencies_seconds` metric.

- Tail latency of database queries
  - High tail latency can indicate the PostgreSQL database is low in resources.
  - Use the `coderd_db_query_latencies_seconds` metric.

### How to capture control plane metrics with Prometheus

Edit your Helm `values.yaml` to capture metrics from the control plane and external provisioner daemons with
[Prometheus](../../admin/integrations/prometheus.md):

1. Enable Prometheus metrics:

   ```yaml
   CODER_PROMETHEUS_ENABLE=true
   ```

1. Enable database metrics:

   ```yaml
   CODER_PROMETHEUS_COLLECT_DB_METRICS=true
   ```

1. For a high scale deployment, configure agent stats to avoid large cardinality or disable them:

   - Configure agent stats:

     ```yaml
     CODER_PROMETHEUS_AGGREGATE_AGENT_STATS_BY=agent_name
     ```

   - Disable agent stats:

     ```yaml
     CODER_PROMETHEUS_COLLECT_AGENT_STATS=false
     ```

## Control plane

### Locality

If increased availability of the Coder API is a concern, deploy at least three
control plane instances. Spread the instances across nodes with anti-affinity rules in
Kubernetes or in different availability zones of the same geographic region.

Do not deploy in different geographic regions.

Control plane instances need to be able to communicate with one another directly with low latency, under 10&nbsp;ms.
Note that this is for the availability of the Coder API.
Workspaces are not fault tolerant unless they are explicitly built that way at the template level.

Deploy control plane instances as geographically close to PostgreSQL as possible.
Low-latency communication (under 10&nbsp;ms) with Postgres is essential for control plane performance.

### Scaling

The control plane can be scaled both vertically for bigger instances and horizontally
for more instances.

Aim to keep the number of control plane instances relatively small, preferably
under ten instances, and opt for vertical scale over horizontal scale after
meeting availability requirements.

Coder's
[validated architectures](../../install/plan/sizing/index.md)
give specific sizing recommendations for various user scales. These are a useful
starting point, but very few deployments will remain stable at a predetermined
user level over the long term. We recommend monitoring and adjusting resources as needed.

We don't recommend that you autoscale the control plane instances. Instead, scale the
deployment for peak weekly usage.

Although the control plane persists no internal state, it operates as a proxy for end
users to their workspaces in two capacities:

1. As an HTTP proxy when they access workspace applications in their browser via
   the Coder Dashboard.

1. As a DERP proxy when establishing tunneled connections with CLI tools like
   `coder ssh`, `coder port-forward`, and others, and with desktop IDEs.

Stopping a control plane instance will (momentarily) disconnect any users
currently connecting through that instance. Adding a new instance is not
disruptive, but you should remove instances and perform upgrades during a
maintenance window to minimize disruption.

## Provisioner daemons

### Locality

We recommend that you run one or more
[provisioner daemon deployments external to the control plane](../../install/operate/provisioners/index.md)
and disable provisioner daemons within your control plane.
This allows you to scale them independently of the control plane:

```yaml
CODER_PROVISIONER_DAEMONS=0
```

We recommend deploying provisioner daemons within the same cluster as the
workspaces they will provision or are hosted in.

- This gives them a low-latency connection to the APIs they will use to
  provision workspaces and can speed builds.

- It allows provisioner daemons to use in-cluster mechanisms (for example
  Kubernetes service account tokens, AWS IAM Roles, and others) to authenticate with
  the infrastructure APIs.

- If you deploy workspaces in multiple clusters, run multiple provisioner daemon
  deployments and use template tags to select the correct set of provisioner
  daemons.

- Provisioner daemons need to be able to connect to the control plane, but this does not need
  to be a low-latency connection.

Provisioner daemons make no direct connections to the PostgreSQL database, so
there's no need for locality to the Postgres database.

### Scaling

Each provisioner daemon instance can handle a single workspace build job at a
time. Therefore, the maximum number of simultaneous builds your Coder deployment
can handle is equal to the number of provisioner daemon instances within a tagged
deployment.

If users experience unacceptably long queues for workspace builds to start,
consider increasing the number of provisioner daemon instances in the affected
cluster.

You might need to automatically scale the number of provisioner daemon instances
throughout the day to meet demand.

If you stop instances with `SIGHUP`, they will complete their current build job
and exit. `SIGINT` will cancel the current job, which will result in a failed build.
Ensure your autoscaler waits long enough for your build jobs to complete before
it kills the provisioner daemon process.

If you deploy in Kubernetes, we recommend a single provisioner daemon per pod.
On a virtual machine (VM), you can deploy multiple provisioner daemons, ensuring
each has a unique `CODER_CACHE_DIRECTORY` value.

Coder's
[validated architectures](../../install/plan/sizing/index.md)
give specific sizing recommendations for various user scales. Since the
complexity of builds varies significantly depending on the workspace template,
consider this a starting point. Monitor queue times and build times and adjust
the number and size of your provisioner daemon instances.

## PostgreSQL

PostgreSQL is the primary persistence layer for all of Coder's deployment data.
We also use `LISTEN` and `NOTIFY` to coordinate between different instances of
the control plane.

### Locality

Control plane instances must have low-latency connections (under 10&nbsp;ms) to PostgreSQL.
If you use multiple PostgreSQL replicas in a clustered config, these must also be low-latency with respect to one another.

### Scaling

Prefer scaling PostgreSQL vertically rather than horizontally for best
performance. Coder's
[validated architectures](../../install/plan/sizing/index.md)
give specific sizing recommendations for various user scales.

### Connection pool tuning

The control plane maintains a pool of connections to PostgreSQL. You can tune the
pool size with the following settings:

> [!NOTE]
> When adjusting these settings, please ensure that your PostgreSQL Server has `max_connections`
> set appropriately to accommodate all control plane replicas multiplied by the
> maximum number of open connections. We recommend configuring an additional 20%
> of connections to account for churn and other clients.
>
> Also note that increasing `max_connections` will result in potentially higher
> CPU and RAM usage, so you'll need to monitor accordingly.

- `--postgres-conn-max-open` (env: `CODER_PG_CONN_MAX_OPEN`): Maximum number of open
  connections. Default: 10.
- `--postgres-conn-max-idle` (env: `CODER_PG_CONN_MAX_IDLE`): Maximum number of idle
  connections kept in the pool. Default: "auto", which uses max open / 3.

When a connection is returned to the pool and the idle pool is already full, the
connection is closed immediately. This can cause connection establishment
overhead (churn) when load fluctuates. Monitor these metrics to understand your
connection pool behavior:

- **Capacity**: `go_sql_max_open_connections - go_sql_in_use_connections` shows
  how many connections are available for new requests. If this is 0, control
  plane performance will start to degrade. This just provides a point-in-time view
  of the connections, however.

  For a more systematic view, consider running
  `sum by (pod) (increase(go_sql_wait_duration_seconds_total[1m]))` to see how long
  each Coder replica spent waiting on the connection pool (i.e. no free connections);
  `sum by (pod) (increase(go_sql_wait_count_total[$__interval]))` shows how many
  connections were waited for.

  If either of these values seem unacceptably high, try tuning the above settings.
- **Churn**: `sum(rate(go_sql_max_idle_closed_total[$__rate_interval]))` shows
  how many connections are being closed because the idle pool is full.

If you see high churn, consider increasing `--pg-conn-max-idle` to keep more
connections ready for reuse. If you see capacity consistently near zero,
consider increasing `--pg-conn-max-open`.

## Workspace proxies

Workspace proxies proxy HTTP traffic from end users to workspaces for Coder apps
defined in the templates, and HTTP ports opened by the workspace. By default
they also include a DERP Proxy.

### Locality

We recommend each geographic cluster of workspaces have an associated deployment
of workspace proxies. This ensures that users always have a near-optimal proxy
path.

### Scaling

Workspace proxy load is determined by the amount of traffic they proxy.

Monitor CPU, memory, and network I/O utilization to decide when to resize
the number of proxy instances.

Scale for peak demand and scale down or upgrade during a maintenance window.

We do not recommend autoscaling the workspace proxies because many applications
use long-lived connections such as websockets, which would be disrupted by
stopping the proxy.

## Workspaces

Workspaces represent the vast majority of resources in most Coder deployments.
Because they are defined by templates, there is no one-size-fits-all advice for
scaling workspaces.

### Hard and soft cluster limits

All Infrastructure as a Service (IaaS) clusters have limits to what can be
simultaneously provisioned. These could be hard limits, based on the physical
size of the cluster, especially in the case of a private cloud, or soft limits,
based on configured limits in your public cloud account.

It is important to be aware of these limits and monitor Coder workspace resource
utilization against the limits, so that a new influx of users don't encounter
failed builds. Monitoring these is outside the scope of Coder, but we recommend
that you set up dashboards and alerts for each kind of limited resource.

As you approach soft limits, you can request limit increases to keep growing.

As you approach hard limits, consider deploying to additional cluster(s).

### Workspaces per node

Many development workloads are "spiky" in their CPU and memory requirements, for
example, they peak during build/test and then lower while editing code.
This leads to an opportunity to efficiently use compute resources by packing multiple
workspaces onto a single node. This can lead to better experience (more CPU and
memory available during brief bursts) and lower cost.

There are a number of things you should consider before you decide how many
workspaces you should allow per node:

- "Noisy neighbor" issues: Users share the node's CPU and memory resources and might
be susceptible to a user or process consuming shared resources.

- If the shared nodes are a provisioned resource, for example, Kubernetes nodes
  running on VMs in a public cloud, then it can sometimes be a challenge to
  effectively autoscale down.

  - For example, if half the workspaces are stopped overnight, and there are ten
    workspaces per node, it's unlikely that all ten workspaces on the node are
    among the stopped ones.

  - You can mitigate this by lowering the number of workspaces per node, or
    using autostop policies to stop more workspaces during off-peak hours.

- If you do overprovision workspaces onto nodes, keep them in a separate node
  pool and schedule the control plane, PostgreSQL, and workspace proxy
  components on a different node pool to avoid resource spikes
  affecting them.

Coder customers have had success with both:

- One workspace per AWS VM
- Lots of workspaces on Kubernetes nodes for efficiency

### Cost control

- Use quotas to discourage users from creating many workspaces they don't need
  simultaneously.

- Label workspace cloud resources by user, team, organization, or your own
  labelling conventions to track usage at different granularities.

- Use autostop requirements to bring off-peak utilization down.

## Networking

Set up your network so that most users can get direct, peer-to-peer connections
to their workspaces. This drastically reduces the load on the control plane and
workspace proxy instances.

## Next steps

- [Scale Tests and Utilities](../../install/validate/scale-testing/utility.md)
- [Scale Testing](../../install/validate/scale-testing.md)

---

# Security - best practices

Source: https://coder.com/docs/tutorials/best-practices/security-best-practices

December 16, 2024

---

This best practices guide is separated into parts to help you secure aspects of
your Coder deployment.

Each section briefly introduces each threat model, then suggests steps or
concepts to help implement security improvements such as authentication and
encryption.

As with any security guide, the steps and suggestions outlined in this document
are not meant to be exhaustive and do not offer any guarantee.

## Control plane

The control plane is the core of a Coder deployment.

If the control plane is compromised in a security incident, it can affect every
other part of your deployment. Even a successful read-only attack against the
control plane could result in a complete compromise of the Coder deployment if
credentials are stolen.

### User authentication

Configure [OIDC authentication](../../admin/users/oidc-auth/index.md) against your
organization’s Identity Provider (IdP), such as Okta, to allow single-sign on.

1. Enable and require two-factor authentication in your identity provider.
1. Enable [IdP Sync](../../admin/users/idp-sync.md) to manage users’ roles and
   groups in Coder.
1. Use SCIM to automatically suspend users when they leave the organization.

This allows you to manage user credentials according to your company’s central
requirements, such as password complexity, 2FA, PassKeys, and others.

Using IdP sync and SCIM means that the central Identity Provider is the source
of truth, so that when users change roles or leave, their permissions in Coder
are automatically up to date.

### Encryption in transit

Place Coder behind a TLS-capable reverse-proxy/load balancer and enable
[Strict Transport Security](../../reference/cli/server/index.md#--strict-transport-security)
so that connections from end users are always encrypted.

Enable [TLS](../../reference/cli/server/index.md#--tls-address) on the control plane and
encrypt traffic from the reverse-proxy/load balancer to the control plane, so that
even if an attacker gains access to your network, they will not be able to snoop
on control plane traffic.

### Encryption at rest

The control plane persists no state locally. No action is required.

### Control plane logs and audit logs

Capture the logging output of all control plane instances and persist them.

Retain all logs for a minimum of thirty days, ideally ninety days. Filter audit
logs (which have `msg: audit_log`) and retain them for a minimum of two years
(ideally five years) in a secure system that resists tampering.

If a security incident with Coder does occur, audit logs are invaluable in
determining the nature and scope of the impact.

### Disable path-based apps

For production deployments, we recommend that you disable path-based apps after you've configured a wildcard access URL.

Path-based apps share the same origin as the Coder API, which can be convenient for trialing Coder,
but can expose the deployment to cross-site-scripting (XSS) attacks in production.
A malicious workspace could reuse Coder cookies to call the API or interact with other workspaces owned by the same user.

1. [Enable sub-domain apps with a wildcard DNS record](../../admin/setup/index.md#wildcard-access-url) (like `*.coder.example.com`)

1. Disable path-based apps:

   ```sh
   coder server --disable-path-apps
   # or
   export CODER_DISABLE_PATH_APPS=true
   ```

By default, Coder mitigates the impact of having path-based apps enabled, but we still recommend disabling it to prevent
malicious workspaces accessing other workspaces owned by the same user or performing requests against the Coder API.

If you do keep path-based apps enabled:

- Path-based apps cannot be shared with other users unless you start `coder server` with `--dangerous-allow-path-app-sharing`.
- Users with the site `owner` role cannot use their admin privileges to access path-based apps for workspaces unless
  `coder server` is started with `--dangerous-allow-path-app-site-owner-access`.

## PostgreSQL

PostgreSQL is the persistent datastore underlying the entire Coder deployment.
If the database is compromised, it may leave every other part of your deployment
vulnerable.

Coder session tokens and API keys are salted and hashed, so a read-only
compromise of the database is unlikely to allow an attacker to log into Coder.
However, the database contains the Terraform state for all workspaces, OIDC
tokens, and agent tokens, so it is possible that a read-only attack could enable
lateral movement to other systems.

A successful attack that modifies database state could be escalated to a full
takeover of an owner account in Coder which could lead to a complete compromise
of the Coder deployment.

### Authentication

1. Generate a strong, random password for accessing PostgreSQL and store it
   securely.

1. Use environment variables to pass the PostgreSQL URL to Coder.

1. If on Kubernetes, use a Kubernetes secret to set the environment variable.

### Encryption in transit

Enable TLS on PostgreSQL and set `sslmode=verify-full` in your
[postgres URL](../../reference/cli/server/index.md#--postgres-url) on the control plane.
This configures the control plane to only establish TLS connections to PostgreSQL and
check that the PostgreSQL server’s certificate is valid and matches the expected
hostname.

### Encryption at rest

Run PostgreSQL on servers with full disk encryption enabled and configured.

Coder supports
[encrypting some particularly sensitive data](../../admin/security/database-encryption.md)
including OIDC tokens using an encryption key managed independently of the
database, so even a user with full administrative privileges on the PostgreSQL
server(s) cannot read the data without the separate key.

If you use this feature:

1. Generate a random encryption key and store it in a central secrets management
   system like Vault.

1. Inject the secret using an environment variable.

   - If you're using Kubernetes, use a Kubernetes secret rather than including
     the secret directly in the podspec.

1. Follow your organization's policies about key rotation on a fixed schedule.

   - If you suspect the key has been leaked or compromised,
     [rotate the key immediately](../../admin/security/database-encryption.md#rotate-keys).

## Provisioner daemons

Provisioner daemons are deployed with credentials that give them power to make
requests to cluster/cloud APIs.

If one of those credentials is compromised, the potential severity of the
compromise depends on the permissions granted to the credentials, but will
almost certainly include code execution inside the cluster/cloud since the whole
purpose of Coder is to deploy workspaces in the cluster/cloud that can run
developer code.

In addition, provisioner daemons are given access to parameters entered by end
users, which could include sensitive data like credentials for additional
systems.

### External provisioner daemons

When Coder workspaces are deployed into multiple clusters/clouds, or workspaces
are in a different cluster/cloud than the control plane, use external provisioner
daemons.

Running provisioner daemons within the same cluster/cloud as the workspaces they
provision:

- Allows you to use infrastructure-provided credentials (see **Authentication**
  below) which are typically easier to manage and have shorter lifetimes than
  credentials issued outside the cloud/cluster.
- Means that you don’t have to open any ingress ports on the clusters/clouds
  that host workspaces.
  - The external provisioner daemons dial out to the control plane.
  - Provisioner daemons run in the cluster, so you don’t need to expose
    cluster/cloud APIs externally.
- Each cloud/cluster is isolated, so a compromise of a provisioner daemon is
  limited to a single cluster.

### Authentication

1. Use a [scoped key](../../install/operate/provisioners/index.md#scoped-key-recommended) to
   authenticate the provisioner daemons with Coder. These keys can only be used
   to authenticate provisioner daemons (not other APIs on the control plane).

1. Store the keys securely and use environment variables to pass them to the
   provisioner daemon.

1. If on Kubernetes, use a Kubernetes secret to set the environment variable.

1. Tag provisioners with identifiers for the specific cluster/cloud.

   This allows your templates to target a specific cluster/cloud such as for
   geographic proximity to the end user, or for specific features like GPUs or
   managed services.

1. Scope your keys to organizations and the specific cluster/cloud using the
   same tags when creating the keys.

   This ensures that a compromised key will not allow an attacker to gain access
   to jobs for other clusters or organizations.

Provisioner daemons should have access only to cluster/cloud API credentials for
the specific cluster/cloud they are for. This ensures that compromise of one
Provisioner Daemon does not compromise all clusters/clouds.

Deploy the provisioner daemon to the cloud and leverage infrastructure-provided
credentials, if available:

- [Service account tokens on Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/)
- [IAM roles for EC2 on AWS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html)
- [Attached service accounts on Google Cloud](https://cloud.google.com/iam/docs/attach-service-accounts)

### Encryption in transit

Enable TLS on the control plane and ensure you use an `https://` URL to access the
control plane.

See the **Encryption in transit** subheading of the
[Templates](#workspace-templates) section for more about encrypting
cluster/cloud API calls.

### Encryption at rest

Run provisioner daemons only on systems with full disk encryption enabled.

- Provisioner daemons temporarily persist terraform template files and resource
  state to disk. Either of these could contain sensitive information, including
  credentials.

  This temporary state is on disk only while actively building workspaces, but
  an attacker who compromises physical disks could successfully read this
  information if not encrypted.

- Provisioner daemons store cached copies of Terraform provider binaries. These
  are generally not sensitive in terms of confidentiality, but it is important
  to maintain their integrity. An attacker that can modify these binaries could
  inject malicious code.

## Workspace proxies

Workspace proxies authenticate end users and then proxy network traffic to
workspaces.

Coder takes care to ensure the user credentials processed by workspace proxies
are scoped to application access and do not grant full access to the Coder API
on behalf of the user. Still, a fully compromised workspace proxy would be in a
privileged position to phish unrestricted user credentials.

Workspace proxies have unrestricted access to establish encrypted tunnels to
workspaces and can access any port on any running workspace.

### Authentication

1. Securely store the workspace proxy token generated by
   [`coder wsproxy create`](../../admin/networking/workspace-proxies.md#step-1-create-the-proxy).

1. Inject the token to the workspace proxy process via an environment variable,
   rather than via an argument.

1. If on Kubernetes, use a Kubernetes secret to set the environment variable.

### Encryption in transit

Enable TLS on the control plane and ensure you use an `https://` URL to access the
control plane.

Communication to the proxied workspace applications is always encrypted with
Wireguard. No action is required.

### Encryption at rest

Workspace proxies persist no state locally. No action is required.

## Workspace templates

Coder templates are executed on provisioner daemons and can include arbitrary
code via the
[local-exec provisioner](https://developer.hashicorp.com/terraform/language/resources/provisioners/local-exec).

Furthermore, Coder templates are designed to provision compute resources in one
or more clusters/clouds, and template authors are generally in full control over
code and scripts executed by the workspace agent in those compute resources.

This means that template admins have remote code execution privileges for any
provisioner daemons in their organization and within any cluster/cloud those
provisioner daemons are credentialed to access.

Template admin is a powerful, highly-trusted role that you should not assign
lightly. Instead of directly assigning the role to anyone who might need to edit
a template, use [GitOps](#gitops) to allow users to author and edit templates.

## Secrets

Never include credentials or any other secrets directly in templates, including
in `.tfvars` or other files uploaded with the template.

Instead do one of the following:

- Store secrets in a central secrets manager.

  - Access the secrets at build time via a Terraform provider.

    This can be through
    [Vault](https://registry.terraform.io/providers/hashicorp/vault/latest/docs)
    or
    [AWS Secrets Manager](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/secretsmanager_secret).

- Place secrets in `TF_VAR_*` environment variables.

  - Provide the secrets to the relevant Provisioner Daemons and access them via
    Terraform variables with `sensitive = true`.

- Use Coder parameters to accept secrets from end users at build time.

Coder does not attempt to obscure the contents of template files from users
authorized to view and edit templates, so secrets included directly could
inadvertently appear on screen while template authors do their work.

Template versions are persisted indefinitely in the PostgreSQL database, so if
secrets are inadvertently included, they should be revoked as soon as practical.
Pushing a new template version does not expunge them from the database. Contact
support if you need assistance expunging any particularly sensitive data.

### Encryption in transit

Always use encrypted transport to access any infrastructure APIs. Crucially,
this protects confidentiality of the credentials used to access the APIs.

Configuration of this depends on the specific Terraform providers in use and is
beyond the scope of this document.

### Encryption at rest

While your most privileged secrets should never be included in template files,
they may inevitably contain confidential or sensitive data about your operations
and/or infrastructure.

- Ensure that operators who write, review or modify Coder templates are working
  on laptops/workstations with full disk encryption, or do their work inside a
  Coder workspace with full disk encryption.
- Ensure [PostgreSQL](#postgresql) is encrypted at rest.
- Ensure any [source code repositories that store templates](#gitops) are
  encrypted at rest and have appropriate access controls.

### GitOps

GitOps is the practice of using a Git repository as the source of truth for
operational config and reconciling the config in Git with operational systems
each time the `main` (or, archaically, `master`) branch of the repository is
updated.

1. Store Coder templates in a single Git repository, or a single repository per
   Coder organization, and use the
   [Coderd Terraform provider](https://registry.terraform.io/providers/coder/coderd/latest/docs/resources/template)
   to push changes from the main branch to Coder using a CI/CD tool.

   This gives you an easily browsable, auditable history of template changes and
   who made them. Coder audit logs establish who and when changes happen, but
   git repositories are particularly handy for analyzing exactly what changes to
   templates are made.

1. Use a Coder user account exclusively for the purpose of pushing template
   changes and do not give any human users the credentials.

   This ensures any actions taken by the account correspond exactly to CI/CD
   actions from the repository and allows you to avoid granting the template
   admin role widely in your organization.

1. Use
   [GitHub branch protection](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches),
   or the equivalent for your source repository to enforce code review of
   changes to templates.

   Code review increases the chance that someone will catch a potential security
   bug in your template.

These protections also mitigate the risk of a single trusted insider “going
rogue” and acting unilaterally to maliciously modify Coder templates.

## Workspaces

The central purpose of Coder is to give end users access to managed compute in
clusters/clouds designated by Coder’s operators (like platform or developer
experience teams). End users are granted shell access and from there can execute
arbitrary commands.

This means that end users have remote code execution privileges within the
clusters/clouds that host Coder workspaces.

It is important to limit Coder users to trusted insiders and/or take steps to
constrain malicious activity that could be undertaken from a Coder workspace.

Example constraints include:

- Network policy or segmentation
- Runtime protections on the workspace host (e.g. SELinux)
- Limiting privileges of the account or role assigned to the workspace such as a
  service account on Kubernetes, or IAM role on public clouds
- Monitoring and/or auditing for suspicious activity such as cryptomining or
  exfiltration

### Outbound network access

Identify network assets like production systems or highly confidential
datastores and configure the network to limit access from Coder workspaces.

If production systems or confidential data reside in the same cluster/cloud, use
separate node pools and network boundaries.

If extraordinary access is required, follow
[Zero Trust](https://en.wikipedia.org/wiki/Zero_trust_security_model)
principles:

- Authenticate the user and the workspace using strong cryptography
- Apply strict authorization controls
- Audit access in a tamper resistant secure store

Consider the network assets end users will need to do their job and the level of
trust the company has with them. In-house full-time employees have different
access than temporary contractors or third-party service providers. Restrict
access as appropriate.

A non-exclusive list of network assets to consider:

- Access to the public Internet
  - If end users will access the workspace over the public Internet, you must
    allow outbound access to establish the encrypted tunnels.
- Access to internal corporate networks
  - If end users will access the workspace over the corporate network, you must
    allow outbound access to establish the encrypted tunnels.
- Access to staging or production systems
- Access to confidential data (e.g. payment processing data, health records,
  personally identifiable information)
- Access to other clusters/clouds

### Inbound network access

Coder manages inbound network access to your workspaces via a set of Wireguard
encrypted tunnels. These tunnels are established by sending outbound packets, so
on stateful firewalls, disable inbound connections to workspaces to ensure
inbound connections are handled exclusively by the encrypted tunnels.

#### DERP

[DERP](https://tailscale.com/kb/1232/derp-servers) is a relay protocol developed
by Tailscale.

The control plane and Workspace Proxies include a DERP service by default. Tailcale
also runs a set of public DERP servers, globally distributed.

All DERP messages are end-to-end encrypted, so the DERP service only learns the
(public) IP addresses of the participants.

If you consider these addresses or the fact that pairs of them communicate over
DERP to be sensitive, stick to the Coder-provided DERP services which run on
your own infrastructure. If not, feel free to configure Tailscale DERP servers
for global coverage.

#### STUN

[STUN](https://en.wikipedia.org/wiki/STUN) is an IETF standard protocol that
allows network endpoints behind NAT to learn their public address and port
mappings. It is an essential component of Coder’s networking to enable encrypted
tunnels to be established without a relay for best performance.

Coder does not ship with a STUN service because it needs to be run directly
connected to the network, not behind a reverse proxy or load balancer as Coder
usually is.

STUN messages are not encrypted, but do not transmit any tunneled data, they
simply query the public address and ports. As such, a STUN service learns the
public address and port information such as the address and port on the NAT
device of Coder workspaces and the end user's device if STUN is configured.

Unlike DERP, it doesn’t definitively learn about communicating pairs of IPs.

If you consider the public IP and port information to be sensitive, do not use
public STUN servers.

You may choose not to configure any STUN servers, in which case most workspace
traffic will need to be relayed via DERP. You may choose to deploy your own STUN
servers, either on the public Internet, or on your corporate network and
[configure Coder to use it](../../reference/cli/server/index.md#--derp-server-stun-addresses).

If you do not consider the addresses and ports to be sensitive, we recommend
using the default set of STUN servers operated by Google.

#### Workspace apps

Coder workspace apps are a way to allow users to access web applications running
in the workspace via the control plane or Workspace Proxy.

1. [Disable workspace apps on sub-paths](../../reference/cli/server/index.md#--disable-path-apps)
   of the main Coder domain name.

1. [Use a separate, wildcard domain name](../../admin/setup/index.md#wildcard-access-url)
   for forwarding.

   Because of the default
   [same-origin policy](https://en.wikipedia.org/wiki/Same-origin_policy) in
   browsers, serving web apps on the main Coder domain would allow those apps to
   send API requests to the control plane, authenticated as the logged-in user
   without their explicit consent.

#### Port sharing

Coder supports the option to allow users to designate specific network ports on
their workspace as shared, which allows others to access those ports via the
control plane.

Consider restricting the maximum sharing level for workspaces, located in the
template settings for the corresponding template.

### Encryption at rest

Deploy Coder workspaces using full disk encryption for all volumes.

This mitigates attempts to recover sensitive data in the workspace by attackers
who gain physical access to the disk(s).

---

# Speed up your Coder templates and workspaces

Source: https://coder.com/docs/tutorials/best-practices/speed-up-templates

October 31, 2024

---

If it takes your workspace a long time to start, find out why and make some
changes to your Coder templates to help speed things up.

## Monitoring

You can monitor [Coder logs](../../admin/monitoring/logs.md) through the
system-native tools on your deployment platform, or stream logs to tools like
Splunk, Datadog, Grafana Loki, and others.

### Workspace build timeline

Use the **Build timeline** to monitor the time it takes to start specific
workspaces. Identify long scripts, resources, and other things you can
potentially optimize within the template.

![Screenshot of a workspace and its build timeline](../../images/best-practice/build-timeline.png)

You can also retrieve this detail programmatically from the API:

```sh
curl -X GET https://coder.example.com/api/v2/workspacebuilds/{workspacebuild}/timings \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

Visit the
[API documentation](../../reference/api/builds.md#get-workspace-build-timings-by-id)
for more information.

### Coder Observability Chart

Use the [Observability Helm chart](https://github.com/coder/observability) for a
pre-built set of dashboards to monitor your Coder deployments over time. It
includes pre-configured instances of Grafana, Prometheus, Loki, and Alertmanager
to ingest and display key observability data.

We recommend that all administrators deploying on Kubernetes or on an existing
Prometheus or Grafana stack set the observability bundle up with the control
plane from the start. For installation instructions, visit the
[observability repository](https://github.com/coder/observability?tab=readme-ov-file#installation),
or our [Kubernetes installation guide](../../install/server/kubernetes/index.md).

### Enable Prometheus metrics for Coder

Coder exposes a variety of
[application metrics](../../admin/integrations/prometheus.md#available-metrics),
such as `coderd_provisionerd_job_timings_seconds` and
`coderd_agentstats_startup_script_seconds`, which measure how long the
workspaces take to provision and how long the startup scripts take.

To make use of these metrics, you will need to
[enable Prometheus metrics](../../admin/integrations/prometheus.md#enable-prometheus-metrics)
exposition.

If you are not using the [Observability Chart](#coder-observability-chart), you
will need to install Prometheus and configure it to scrape the metrics from your
Coder installation.

## Provisioners

`coder server` by default provides three built-in provisioner daemons
(controlled by the
[`CODER_PROVISIONER_DAEMONS`](../../reference/cli/server/index.md#--provisioner-daemons)
config option). Each provisioner daemon can handle one single job (such as
start, stop, or delete) at a time and can be resource intensive. When all
provisioners are busy, workspaces enter a "pending" state until a provisioner
becomes available.

### Increase provisioner daemons

Provisioners are queue-based to reduce unpredictable load to the control plane.
If you require a higher bandwidth of provisioner jobs, you can do so by
increasing the
[`CODER_PROVISIONER_DAEMONS`](../../reference/cli/server/index.md#--provisioner-daemons)
config option.

You risk overloading Coder if you use too many built-in provisioners, so we
recommend a maximum of five built-in provisioners per `coderd` replica. For more
than five provisioners, we recommend that you move to
[External Provisioners](../../install/operate/provisioners/index.md) and also consider
[High Availability](../../admin/networking/high-availability.md) to run multiple
`coderd` replicas.

Visit the
[CLI documentation](../../reference/cli/server/index.md#--provisioner-daemons) for
more information about increasing provisioner daemons, configuring external
provisioners, and other options.

### Adjust provisioner CPU/memory

We recommend that you deploy Coder to its own respective Kubernetes cluster,
separate from production applications. Keep in mind that Coder runs development
workloads, so the cluster should be deployed as such, without production-level
configurations.

Adjust the CPU and memory values as shown in
[Helm provisioner values.yaml](../../../helm/provisioner/values.yaml#L134-L141):

```yaml
…
  resources:
    limits:
      cpu: "0.25"
      memory: "1Gi"
    requests:
      cpu: "0.25"
      memory: "1Gi"
…
```

Visit the
[validated architecture documentation](../../install/plan/sizing/index.md#workspace-nodes)
for more information.

## Set up Terraform provider caching

### Template lock file

On each workspace build, Terraform will examine the providers used by the
template and attempt to download the latest version of each provider unless it
is constrained to a specific version. Terraform exposes a mechanism to build a
static list of provider versions, which improves cacheability.

Without caching, Terraform will download each provider on each build, and this
can create unnecessary network and disk I/O.

`terraform init` generates a `.terraform.lock.hcl` which instructs Coder
provisioners to cache specific versions of your providers.

To use `terraform init` to build the static provider version list:

1. Pull your template to your local device:

   ```sh
   coder templates pull <template>
   ```

1. Run `terraform init` inside the template directory to build the lock file:

   ```sh
   terraform init
   ```

1. Push the templates back to your Coder deployment:

   ```sh
   coder templates push <template>
   ```

This bundles up your template and the lock file and uploads it to Coder. The
next time the template is used, Terraform will attempt to cache the specific
provider versions.

### Cache directory

Coder will instruct Terraform to cache its downloaded providers in the
configured [`CODER_CACHE_DIRECTORY`](../../reference/cli/server/index.md#--cache-dir)
directory.

Ensure that this directory is set to a location on disk which will persist
across restarts of Coder or
[external provisioners](../../install/operate/provisioners/index.md), if you're using them.

---

# Reference

Source: https://coder.com/docs/reference

## Automation

All actions possible through the Coder dashboard can also be automated. There
are several ways to extend/automate Coder:

- [coderd Terraform Provider](https://registry.terraform.io/providers/coder/coderd/latest)
- [CLI](../reference/cli/index.md)
- [REST API](../reference/api/index.md)
- [Coder SDK](https://pkg.go.dev/github.com/coder/coder/v2/codersdk)
- [Agent API](../reference/agent-api/index.md)

## Quickstart

Generate a token on your Coder deployment by visiting:

```sh
https://coder.example.com/settings/tokens
```

List your workspaces

```sh
# CLI
coder ls \
  --url https://coder.example.com \
  --token <your-token> \
  --output json

# REST API (with curl)
curl https://coder.example.com/api/v2/workspaces?q=owner:me \
  -H "Coder-Session-Token: <your-token>"
```

## Documentation

We publish an [API reference](../reference/api/index.md) in our documentation.
You can also enable a
[Swagger endpoint](../reference/cli/server/index.md#--swagger-enable) on your Coder
deployment.

## Use cases

We strive to keep the following use cases up to date, but please note that
changes to API queries and routes can occur. For the most recent queries and
payloads, we recommend checking the relevant documentation.

### Users & Groups

- [Manage Users via Terraform](https://registry.terraform.io/providers/coder/coderd/latest/docs/resources/user)
- [Manage Groups via Terraform](https://registry.terraform.io/providers/coder/coderd/latest/docs/resources/group)

### Templates

- [Manage templates via Terraform or CLI](../admin/templates/managing-templates/change-management.md):
  Store all templates in git and update them in CI/CD pipelines.

### Workspace agents

Workspace agents have a special token that can send logs, metrics, and workspace
activity.

- [Custom workspace logs](../reference/api/agents.md#patch-workspace-agent-logs):
  Expose messages prior to the Coder init script running (e.g. pulling image, VM
  starting, restoring snapshot).
  [coder-logstream-kube](https://github.com/coder/coder-logstream-kube) uses
  this to show Kubernetes events, such as image pulls or ResourceQuota
  restrictions.

  ```sh
  curl -X PATCH https://coder.example.com/api/v2/workspaceagents/me/logs \
  -H "Coder-Session-Token: $CODER_AGENT_TOKEN" \
  -d "{
  \"logs\": [
    {
      \"created_at\": \"$(date -u +'%Y-%m-%dT%H:%M:%SZ')\",
      \"level\": \"info\",
      \"output\": \"Restoring workspace from snapshot: 05%...\"
    }
  ]
  }"
  ```

- [Manually send workspace activity](../reference/api/workspaces.md#extend-workspace-deadline-by-id):
  Keep a workspace "active," even if there is not an open connection (e.g. for a
  long-running machine learning job).

  ```sh
  #!/bin/bash
  # Send workspace activity as long as the job is still running

  while true
  do
  if pgrep -f "my_training_script.py" > /dev/null
  then
    curl -X PUT "https://coder.example.com/api/v2/workspaces/$WORKSPACE_ID/extend" \
    -H "Coder-Session-Token: $CODER_AGENT_TOKEN" \
    -d '{
      "deadline": "2019-08-24T14:15:22Z"
    }'

    # Sleep for 30 minutes (1800 seconds) if the job is running
    sleep 1800
  else
    # Sleep for 1 minute (60 seconds) if the job is not running
    sleep 60
  fi
  done
  ```

---

# Glossary

Source: https://coder.com/docs/reference/glossary

This glossary defines the Coder-specific terms and product names you encounter across the documentation.
Each entry gives a short definition and, where it helps, links to the page that covers the term in depth.

> [!IMPORTANT]
> Several Coder terms share the word "agent" but mean different things:
>
> - [Coder Agents](#coder-agents) is the AI product for delegating development work to coding agents.
> - [Agent Relay](#agent-relay) connects a cloud-hosted AI agent provider's hosted sessions to self-hosted workspaces. It is not Coder Agents.
> - A [workspace agent](#workspace-agent) is the process that runs inside a workspace to provide SSH, port forwarding, the web terminal, and other services.
> - [`coder_agent`](#coder_agent) is the Terraform resource in a template that declares a workspace agent.

## A

### Agent API

The API a workspace agent uses to report logs, metrics, and activity.
Refer to the [Agent API reference](./agent-api/index.md).

### Agent Firewall

A process-level firewall that enforces domain and verb allowlists on AI agent processes inside a workspace and streams audit logs to `coderd`.
It was previously named Agent Boundaries and uses a sandbox backend, `nsjail` by default or `landjail`.
This feature requires a Premium license.
Refer to [Agent Firewall](../ai-coder/agent-firewall/index.md).

### Agent Relay

A feature that connects a supported cloud-hosted AI agent provider's hosted sessions to self-hosted [workspaces](#workspace).
The provider's orchestration and AI inference stay cloud-hosted; a worker process inside the workspace executes the agent's tool calls.
In [early access](./feature-stages.md#early-access-features).
Refer to [Agent Relay](../ai-coder/agent-relay/index.md).

### AI Gateway

An LLM gateway in `coderd` that authenticates users, forwards traffic to providers such as OpenAI and Anthropic, audits prompts and tool invocations, and centralizes MCP administration.
It was previously named AI Bridge and runs the `aibridged` component in memory inside `coderd`.
This feature requires a Premium license.
Refer to [AI Gateway](../ai-coder/ai-gateway/index.md).

### AI Gateway Proxy

An HTTP proxy component, `aibridgeproxyd`, for AI clients that cannot override their base URL, such as GitHub Copilot.
This feature requires a Premium license.
Refer to [AI Gateway Proxy](../ai-coder/ai-gateway/ai-gateway-proxy/index.md).

### AI Governance

Included with a Premium license, AI Governance unlocks AI Gateway and Agent Firewall.
Refer to [AI Governance](../ai-coder/ai-governance.md).

### Air-gapped deployment

A Coder installation that has no outbound internet access.
Refer to [Air-gapped deployments](../install/prepare/airgap.md).

### Audit logging

Structured logs of user and admin operations.
This is a Premium feature.
Refer to [Audit logs](../admin/security/audit-logs.md).

### Autostop requirement

A template or deployment setting that forcibly stops workspaces on a recurring cadence, for example to apply updates.
Refer to [Workspace scheduling](../admin/templates/managing-templates/schedule.md).

## B

### Built-in roles

The roles Coder predefines at two scopes.
Deployment roles such as Owner, User Admin, Template Admin, and Auditor apply across the deployment, and [organization roles](#organization-roles) apply inside one organization.
Refer to [Groups and roles](../admin/users/groups-roles.md).

## C

### CDE

Cloud development environment, the category of product that hosts development environments on remote infrastructure.
A Coder workspace is a CDE.

### Change management

The GitOps flow that stores templates in Git and pushes them through CI/CD with `coder templates push`.
Refer to [Change management](../admin/templates/managing-templates/change-management.md).

### code-server

The Coder-maintained build of VS Code that runs in the browser.
Refer to [code-server](../user-guides/workspace-access/code-server.md).

### Coder

The self-hosted platform that provisions and manages remote development environments, called workspaces, as code.
`Coder`, the company and the product, is always capitalized.

### Coder Agents

The native, self-hosted AI product for delegating development work and research to coding agents.
The agent loop runs in the control plane, and developers work through the dashboard, the `coder agents` CLI, or the REST API.
Not to be confused with a [workspace agent](#workspace-agent) or the [`coder_agent`](#coder_agent) resource.
Refer to [Coder Agents](../ai-coder/agents/index.md).

### Coder CLI

The single `coder` binary used for admin and user operations.
The same binary runs inside a workspace as the workspace agent through `coder agent`.
Refer to the [CLI reference](./cli/index.md).

### Coder Connect

The Coder Desktop feature that runs a local tunnel so workspaces are reachable at `workspace-name.coder` hostnames.
Refer to [Coder Desktop](../user-guides/desktop/index.md).

### Coder Desktop

A native desktop application that connects your machine to your workspaces so you can reach them by hostname and launch apps without configuring the CLI.
Refer to [Coder Desktop](../user-guides/desktop/index.md).

### Coder extension for VS Code

The editor extension that connects VS Code, and forks such as Cursor and Devin Desktop (formerly Windsurf), to workspaces.
Refer to [VS Code](../user-guides/workspace-access/vscode.md).

### Coder Validated Architecture

Coder's reference designs for sizing and deploying a control plane, abbreviated CVA.
Each design covers a user count, from 1,000 to 10,000, and prescribes a Kubernetes-based deployment with tested component sizes, so a deployment is easier to operate and troubleshoot.
A CVA is guidance rather than a certification: it recommends an architecture, but it doesn't approve yours.
Refer to [Coder Validated Architecture](../install/plan/sizing/index.md).

### Coder Workspaces

The self-hosted platform capability for running cloud development environments, defined with Terraform, on infrastructure you control.
Not to be confused with a [workspace](#workspace), the individual on-demand development environment a developer creates from a template.
Refer to [About Coder](../README.md#coder-workspaces).

### `coder server`

The CLI command that starts [`coderd`](#coderd).
Use this name only for the command a reader runs, not as a name for the [control plane](#control-plane) itself.
Refer to the [`coder server` reference](./cli/server/index.md).

### `coder_agent`

The Terraform resource that declares a [workspace agent](#workspace-agent) inside a template.
Refer to the [`coder_agent` resource](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/agent).

### `coder_app`

The Terraform resource that declares an app, IDE, or URL entry surfaced on the workspace page, such as VS Code Web, JupyterLab, or code-server.
Refer to the [`coder_app` resource](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/app).

### `coder_metadata`

The Terraform resource that surfaces static resource information in the dashboard.
Refer to the [`coder_metadata` resource](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/metadata).

### `coder_script`

The Terraform resource that runs a shell script inside the workspace on start or stop, or on demand.
Refer to the [`coder_script` resource](https://registry.terraform.io/providers/coder/coder/latest/docs/resources/script).

### `coderd`

The process that runs the [control plane](#control-plane), started with [`coder server`](#coder-server).
Use `coderd` for the process itself, such as in metric names, log output, configuration flags, and troubleshooting steps.
Introduce it on first use in a page as "`coderd`, the process that runs the control plane".
Refer to [Architecture](../install/plan/architecture.md).

### codersdk

The Go SDK that the CLI and dashboard use and that you can use for automation.
Refer to the [`codersdk` package](https://pkg.go.dev/github.com/coder/coder/v2/codersdk).

<!-- "Coding" is an adjective in this glossary term, not a task verb. -->
<!-- vale Coder.GerundHeading = NO -->

### Coding agent

<!-- vale Coder.GerundHeading = YES -->

An AI agent that reads and writes code on a developer's behalf, such as Claude Code or Coder Agents.
Refer to [AI in Coder](../ai-coder/index.md).

### Community

The free, open-source tier of Coder.

### Computational resource

A resource that provides compute for the workspace, such as a virtual machine or container, and typically runs the workspace agent.

### Connection logs

Structured logs of connections to workspaces, such as SSH and application sessions.
This is a Premium feature.
Refer to [Connection logs](../admin/monitoring/connection-logs.md).

### Control plane

The component that serves the Coder API and dashboard, brokers connections to workspaces, and coordinates provisioners.
It is implemented by the [`coderd`](#coderd) process and also runs the agent loop for [Coder Agents](#coder-agents).
Use *control plane* in prose, diagrams, and any planning, sizing, architecture, or security discussion.
Do not call it "the Coder server", and do not describe it generically as "a service".

### Custom roles

Roles an administrator defines inside an organization from a chosen set of permissions.
This is a Premium feature.
Refer to [Groups and roles](../admin/users/groups-roles.md).

### CVA

Refer to [Coder Validated Architecture](#coder-validated-architecture).

## D

### Deployment

A single installation of Coder, comprising the control plane, its provisioners, and its database.

### Deployment ID

The unique identifier for a Coder deployment.
You provide it when you request a trial or a license.

### DERP

Designated Encrypted Relay for Packets.
The Tailnet uses DERP relays to carry traffic when a direct peer-to-peer connection between two nodes is not possible.
Refer to [Networking](../admin/networking/index.md).

### Dev container

An environment that conforms to the [Development Container Specification](https://containers.dev/) and is defined by a `devcontainer.json` file.
`Dev Containers` is the Coder feature that runs dev containers inside a workspace.
Refer to [Dev containers](../admin/templates/extending-templates/devcontainers.md).

### `display_apps`

A field on `coder_agent` that toggles the built-in agent apps, such as `vscode`, `vscode_insiders`, `web_terminal`, `ssh_helper`, and `port_forwarding_helper`.
The enabled apps appear as buttons in the row on the workspace page.
Refer to [Web IDEs](../admin/templates/extending-templates/web-ides.md).

### Dormancy

Automatic cleanup of workspaces that stay inactive past a threshold, up to and including deletion.
This is a Premium feature.
Refer to [Workspace scheduling](../admin/templates/managing-templates/schedule.md).

### Dotfiles

Personal shell and editor configuration loaded into a workspace with `coder dotfiles`.
Refer to [Dotfiles](../user-guides/workspace-dotfiles.md).

### Dynamic parameters

Template inputs that can change per build, with conditional visibility and validation.
Refer to [Dynamic parameters](../admin/templates/extending-templates/dynamic-parameters.md).

## E

### Envbuilder

The Coder-built tool that constructs a workspace image from a `devcontainer.json` file without requiring Docker inside the workspace.
Refer to [Envbuilder](../admin/integrations/devcontainers/envbuilder/index.md) and the [`envbuilder` repository](https://github.com/coder/envbuilder).

### Ephemeral resource

A resource that is destroyed when the workspace stops and recreated on the next start.
Refer to [Resource persistence](../admin/templates/extending-templates/resource-persistence.md).

### External authentication

In-workspace OAuth to Git providers, artifact registries, and similar services, configured with `CODER_EXTERNAL_AUTH_*` variables.
Refer to [External authentication](../admin/external-auth/index.md).

### External provisioner

A `provisionerd` that runs outside `coderd`, tagged so specific templates route to it, for example to reach an isolated network or to scale build throughput.
Refer to [External provisioners](../install/operate/provisioners/index.md).

### External workspace

A workspace that runs on infrastructure Coder did not provision, connected to Coder through an agent.
This is a Premium feature in early access.
Refer to [External workspaces](../admin/templates/managing-templates/external-workspaces.md).

## F

### Feature stages

The Early Access, Beta, and General Availability labels that describe how production-ready a feature is.
Refer to [Feature stages](./feature-stages.md).

## G

### Group

A collection of users used to grant template and workspace permissions and to apply quotas.
Refer to [Groups and roles](../admin/users/groups-roles.md).

## H

### Headless authentication

Authentication for automated users and service accounts that cannot complete an interactive browser login.
Refer to [Headless authentication](../admin/users/headless-auth.md).

### High availability

Running multiple `coderd` replicas behind a load balancer for redundancy and scale.
This is a Premium feature.
Refer to [High availability](../admin/networking/high-availability.md).

## I

### IDE agent

A coding agent embedded in an editor or IDE, such as Cursor, connected to a Coder workspace.
Refer to [IDE agents](../ai-coder/ide-agents.md).

### IdP sync

Automatic mapping of identity-provider claims to Coder groups, roles, and organizations.
This is a Premium feature.
Refer to [IdP sync](../admin/users/idp-sync.md).

### Infrastructure as code

The practice of defining infrastructure in version-controlled configuration files.
Coder templates are infrastructure as code, written in Terraform.

## L

### License key

A signed token applied through the dashboard or with `coder licenses add`.
Coder validates the key locally, so it works in air-gapped deployments.
Refer to [Licensing](../install/prepare/licensing.md).

## M

### MCP

Model Context Protocol, the standard for exposing tools and servers to LLM agents.
Coder ships an MCP server and lets admins centrally manage approved MCP servers through AI Gateway.
Refer to [MCP server](../ai-coder/mcp-server.md).

### Module

A reusable Terraform building block that a template composes in.
Coder publishes modules in the [Coder Registry](https://registry.coder.com/).
Refer to [Modules](../admin/templates/extending-templates/modules.md).

## O

### OIDC

OpenID Connect.
Coder supports any specification-compliant OIDC provider for single sign-on.
Refer to [OIDC authentication](../admin/users/oidc-auth/index.md).

### OpenTofu

An open-source alternative to Terraform.
Coder deployments can run a custom Terraform binary such as OpenTofu, though custom Terraform binaries are not officially supported.
Refer to [Provisioning with OpenTofu](../admin/integrations/opentofu.md).

### Organization

An isolation boundary for members, templates, provisioners, and quotas.
Multi-organization support is a Premium feature.
Refer to [Organizations](../admin/users/organizations.md).

### Organization roles

The [built-in roles](#built-in-roles) that apply inside a single organization, such as Organization Admin and Organization Template Admin.
A user can hold different organization roles in each organization they belong to.
Refer to [Organization roles](../admin/users/groups-roles.md#organization-roles).

### Owner

The top-level administrator role, with full access to the deployment and every organization.
Refer to [Groups and roles](../admin/users/groups-roles.md).

## P

### Peripheral resource

A supporting resource, such as a disk or network object, that a computational resource depends on.

### Persistent resource

A resource that stays provisioned when the workspace stops, so its state survives a restart.
Refer to [Resource persistence](../admin/templates/extending-templates/resource-persistence.md).

### Personal access token

An API token, often abbreviated PAT, that a user creates to authenticate CLI and API requests.
Refer to [Sessions and tokens](../admin/users/sessions-tokens.md).

### Port forwarding

Access to arbitrary workspace ports through the CLI, SSH, or subdomain apps.
Refer to [Port forwarding](../user-guides/workspace-access/port-forwarding.md).

### Prebuilt workspaces

A pool of workspaces provisioned ahead of time and ready to claim, which cuts the time to first launch.
This is a Premium feature.
Refer to [Prebuilt workspaces](../admin/templates/extending-templates/prebuilt-workspaces.md).

### Premium

The paid enterprise tier, which unlocks features such as multi-organization support, high availability, workspace proxies, audit logs, quotas, custom roles, SCIM, and IdP sync.
Visit [Pricing](https://coder.com/pricing).

### Prometheus metrics

Deployment metrics exposed on a `/metrics` endpoint for Prometheus to scrape.
Refer to [Prometheus](../admin/integrations/prometheus.md).

### Provisioner

A `provisionerd` instance that executes template builds.
Refer to [External provisioners](../install/operate/provisioners/index.md).

### Provisioner tags

Key-value tags on templates and provisioner daemons that route a build to a matching provisioner.
Refer to [External provisioners](../install/operate/provisioners/index.md).

### `provisionerd`

The daemon that runs Terraform to create, update, and destroy workspace resources.
It runs bundled with `coderd` by default and can also run externally.
Refer to [External provisioners](../install/operate/provisioners/index.md).

## Q

### Quiet hours

A window during which forced autostops do not run, so they do not interrupt a developer who is working.
Refer to [Workspace scheduling](../user-guides/workspace-scheduling.md).

## R

### RBAC

Role-based access control, the model Coder uses to grant permissions through roles.
Refer to [Groups and roles](../admin/users/groups-roles.md).

### Registry

The [Coder Registry](https://registry.coder.com/), where Coder publishes reusable templates and modules.

### Release channels

Coder's supported release lines: mainline, stable, and Extended Support Release.
Refer to [Releases](./releases.md).

### Resource

Any Terraform resource created by a template build, whether or not it runs a workspace agent.
Refer to [Resource persistence](../admin/templates/extending-templates/resource-persistence.md).

### Resource quota

A per-user or per-organization cap on the cost of workspace resources.
This is a Premium feature.
Refer to [Quotas](../admin/users/quotas.md).

### REST API

Coder's HTTP API, served under `/api/v2/*`.
Refer to the [API reference](./api/index.md).

## S

### SCIM

Automated user provisioning and deprovisioning driven by your identity provider.
This is a Premium feature.
Refer to [IdP sync](../admin/users/idp-sync.md).

### Service account

A non-human user intended for automation.
You can filter for one in the users list with the `service_account:true` query.
Refer to [Users](../admin/users/index.md).

### Sessions and tokens

Session cookies authenticate the web dashboard, and API tokens authenticate programmatic access.
Refer to [Sessions and tokens](../admin/users/sessions-tokens.md).

### SSH

Optimized SSH access to a workspace over Coder's Tailnet routing, available through `coder ssh`.
Refer to [Workspace access](../user-guides/workspace-access/index.md).

### SSO

Single sign-on, the pattern of authenticating to Coder through an external identity provider, typically over OIDC.
Refer to [OIDC authentication](../admin/users/oidc-auth/index.md).

### Starter template

A curated example template that ships with Coder for a common platform, such as Docker, Kubernetes, AWS, GCP, or Azure.
Refer to [Create templates](../admin/templates/creating-templates.md).

### Sub-agent (Coder Agents)

A delegated child chat that a parent Coder Agents chat spawns to perform a sub-task, with its own tool allowlist.
Not to be confused with a [dev container sub-agent](#sub-agent-dev-containers).
Refer to [Coder Agents architecture](../ai-coder/agents/architecture.md).

### Sub-agent (dev containers)

The nested workspace agent that Coder runs for a dev container inside a parent workspace, so you can connect to the dev container directly.
This is a Coder term, not part of the Development Container Specification.
Not to be confused with a [Coder Agents sub-agent](#sub-agent-coder-agents).
Refer to [Dev containers](../admin/integrations/devcontainers/integration.md).

### Subdomain apps

Wildcard-hosted URLs that expose a workspace's HTTP services on their own subdomain.
Refer to [Port forwarding](../user-guides/workspace-access/port-forwarding.md).

### Support bundle

A diagnostic archive generated with `coder support bundle` to help debug a deployment.
Refer to [Support bundle](../support/support-bundle.md).

### Supported editors and IDEs

The editors and IDEs that connect to Coder workspaces, including [VS Code](../user-guides/workspace-access/vscode.md), [code-server](../user-guides/workspace-access/code-server.md), [Cursor](../user-guides/workspace-access/cursor.md), [Devin Desktop](../user-guides/workspace-access/devin-desktop.md), [Antigravity](../user-guides/workspace-access/antigravity.md), [Zed](../user-guides/workspace-access/zed.md), and JetBrains IDEs through [Gateway](../user-guides/workspace-access/jetbrains/gateway.md) and [Toolbox](../user-guides/workspace-access/jetbrains/toolbox.md).

### Swagger

An optional OpenAPI endpoint that `coderd` can expose for the REST API.
Refer to the [API reference](./api/index.md).

## T

### Tailnet

The WireGuard-based mesh that connects the control plane, workspace proxies, and workspaces.
Refer to [Networking](../admin/networking/index.md).

### Template

The Terraform configuration that defines the infrastructure and Coder resources, such as the agent, apps, and parameters, that produce a workspace.
Refer to [Templates](../admin/templates/index.md).

### Template hardening

Terraform patterns, such as `prevent_destroy` and `ignore_changes`, that protect persistent resources from accidental destruction.
Refer to [Resource persistence](../admin/templates/extending-templates/resource-persistence.md).

### Template usage insights

Dashboard views and `GET /api/v2/insights/*` endpoints that report active users, app usage, and parameter usage for templates.
Refer to the [Insights API](./api/insights.md).

### Template version

An immutable snapshot of a template.
Workspaces are pinned to a version, and admins can push new versions.
Refer to [Manage templates](../admin/templates/managing-templates/index.md).

### Terraform

The HashiCorp tool Coder uses to define and provision workspace infrastructure.
Visit the [Terraform documentation](https://developer.hashicorp.com/terraform).

## W

### Web terminal

A browser terminal served by the workspace agent.
Refer to [Web terminal](../user-guides/workspace-access/web-terminal.md).

### Workspace

A developer's on-demand development environment, such as a virtual machine, container, or Kubernetes pod, provisioned from a template.
Not to be confused with [Coder Workspaces](#coder-workspaces), the platform capability.
Refer to [Workspace management](../user-guides/workspace-management.md).

### Workspace agent

The `coder agent` process that runs inside a workspace to provide SSH, port forwarding, the web terminal, IDE connections, liveness checks, metadata, logs, and startup scripts.
A template declares it with the [`coder_agent`](#coder_agent) Terraform resource.
Not to be confused with [Coder Agents](#coder-agents), the AI product.

### Workspace app

An application, IDE, or URL surfaced on the workspace page, declared with the [`coder_app`](#coder_app) resource or enabled through [`display_apps`](#display_apps).
Refer to [Web IDEs](../user-guides/workspace-access/web-ides.md).

### Workspace autostart and autostop

Scheduled policies that start a workspace on a set schedule and stop it after a period of inactivity.
Refer to [Workspace scheduling](../user-guides/workspace-scheduling.md).

### Workspace process logging

A record of the processes executed inside workspaces.
This is a Premium feature.
Refer to [Process logging](../admin/templates/extending-templates/process-logging.md).

### Workspace proxy

A regional proxy that terminates user connections closer to the developer to lower latency.
This is a Premium feature.
Refer to [Workspace proxies](../admin/networking/workspace-proxies.md).

## Learn more

- [Architecture](../install/plan/architecture.md)
- [Coder Agents](../ai-coder/agents/index.md)
- [Templates](../admin/templates/index.md)
- [API reference](./api/index.md)

---

# Releases

Source: https://coder.com/docs/reference/releases

Coder releases are cut directly from main in our
[GitHub](https://github.com/coder/coder) on the first Tuesday of each month.

We recommend enterprise customers test the compatibility of new releases with
their infrastructure on a staging environment before upgrading a production
deployment.

## Release channels

We support four primary release channels, as well as ad-hoc release candidates:

- **Mainline:** The bleeding edge version of Coder
- **Stable:** N-1 of the mainline release
- **Security Support:** N-2 of the mainline release
- **Extended Support Release:** Biannually released version of Coder
- **Release Candidates:** Ad-hoc builds to validate in-development features

We field our mainline releases publicly for one month before promoting them to stable. The security support version, so n-2 from mainline, receives patches
only for security issues or CVEs.

### Mainline releases

- Intended for customers with a staging environment
- Gives earliest access to new features
- May include minor bugs
- All bugfixes and security patches are supported

### Stable releases

- Safest upgrade/installation path
- May not include the latest features
- All bugfixes and security patches are supported

### Security Support

- In-product security vulnerabilities and CVEs are supported

For more information on feature rollout, see our
[feature stages documentation](./feature-stages.md).

### Extended Support Release

- Designed for organizations that prioritize long-term stability
- Receives only critical bugfixes and security patches
- Ideal for regulated environments or large deployments with strict upgrade cycles

ESR releases will be updated with critical bugfixes and security patches that are available to paying customers. This extended support model provides predictable, long-term maintenance for organizations that require enhanced stability. Because ESR forgoes new features in favor of maintenance and stability, it is best suited for teams with strict upgrade constraints. The latest ESR version is [Coder 2.34](https://github.com/coder/coder/releases/tag/v2.34.5).

For more information, see the [Coder ESR announcement](https://coder.com/blog/esr) or the [2.29 to 2.34 ESR Upgrade Guide](../install/operate/upgrade/esr-2.29-2.34-upgrade.md).

### Release Candidates

- Ad-hoc builds that Coder releases to validate in-development features with select customers
- Not guaranteed to be stable or free of bugs
- Features introduced in an RC are not guaranteed to be included in a mainline or stable release
- Not intended for production use

Release candidates give Coder a way to push out builds for customers and other users to try out new, under-development functionality without cutting a new minor version. Unlike mainline and stable releases, RCs do not follow a fixed schedule and carry no guarantees around stability or long-term support. They exist purely as a feedback mechanism: Coder can ship targeted builds, gather real-world input, and iterate before committing changes to the standard release channels.

<a id="installing-stable"></a>

## Install stable

When installing Coder, we generally advise specifying the desired version from
our GitHub [releases page](https://github.com/coder/coder/releases).

You can also use our `install.sh` script with the `stable` flag to install the
latest stable release:

```sh
curl -fsSL https://coder.com/install.sh | sh -s -- --stable
```

Best practices for installing Coder can be found on our [install](../install/index.md)
pages.

## Release schedule
<!-- Autogenerated release calendar from scripts/update-release-calendar.sh -->
<!-- RELEASE_CALENDAR_START -->
| Release name                                     | Release Date       | Status                   | Latest Release                                                   |
|--------------------------------------------------|--------------------|--------------------------|------------------------------------------------------------------|
| [2.29](https://coder.com/changelog/coder-2-29)   | December 02, 2025  | Extended Support Release | [v2.29.19](https://github.com/coder/coder/releases/tag/v2.29.19) |
| [2.32](https://coder.com/changelog/coder-2-32)   | April 14, 2026     | Not Supported            | [v2.32.10](https://github.com/coder/coder/releases/tag/v2.32.10) |
| [2.33](https://coder.com/changelog/coder-2-33)   | May 05, 2026       | Not Supported            | [v2.33.11](https://github.com/coder/coder/releases/tag/v2.33.11) |
| [2.34](https://coder.com/changelog/coder-2-34)   | June 02, 2026      | Extended Support Release | [v2.34.10](https://github.com/coder/coder/releases/tag/v2.34.10) |
| [2.35](https://coder.com/changelog/coder-2-35-1) | July 07, 2026      | Security Support         | [v2.35.6](https://github.com/coder/coder/releases/tag/v2.35.7)   |
| [2.36](https://coder.com/changelog/coder-2-36)   | August 04, 2026    | Stable                   | [v2.36.5](https://github.com/coder/coder/releases/tag/v2.36.5)   |
| [2.37](https://coder.com/changelog/coder-2-37)   | September 01, 2026 | Mainline                 | [v2.37.1](https://github.com/coder/coder/releases/tag/v2.37.1)   |
| 2.38                                             |                    | Not Released             | N/A                                                              |
<!-- RELEASE_CALENDAR_END -->

> [!TIP]
> We publish a
> [`preview`](https://github.com/coder/coder/pkgs/container/coder-preview) image
> `ghcr.io/coder/coder-preview` on each commit to the `main` branch. This can be
> used to test under-development features and bug fixes that have not yet been
> released to [`mainline`](#mainline-releases) or [`stable`](#stable-releases).
>
> The `preview` image is not intended for production use.

### January Releases

Releases on the first Tuesday of January **are not guaranteed to occur** because most of our team is out for the December holiday period. That being said, an ad-hoc release might still occur. We advise not relying on a January release, or reaching out to Coder directly to determine if one will be occurring closer to the release date.

---

# Feature stages

Source: https://coder.com/docs/reference/feature-stages

Some Coder features are released in feature stages before they are generally
available.

If you encounter an issue with any Coder feature, please submit a
[GitHub issue](https://github.com/coder/coder/issues) or join the
[Coder Discord](https://discord.gg/coder).

## Feature stages

| Feature stage                          | Stable | Production-ready | Support               | Description                                                                                                                   |
|----------------------------------------|--------|------------------|-----------------------|-------------------------------------------------------------------------------------------------------------------------------|
| [Early Access](#early-access-features) | No     | No               | GitHub issues         | For staging only. Not feature-complete or stable. Disabled by default.                                                        |
| [Beta](#beta)                          | No     | Not fully        | Docs, Discord, GitHub | Publicly available. In active development with minor bugs. Suitable for staging; optional for production. Not covered by SLA. |
| [GA](#general-availability-ga)         | Yes    | Yes              | License-based         | Stable and tested. Enabled by default. Fully documented. Support based on license.                                            |

## Early access features

- **Stable**: No
- **Production-ready**: No
- **Support**: GitHub issues

Early access features are neither feature-complete nor stable. We do not
recommend using early access features in production deployments.

Coder sometimes releases early access features that are available for use, but
are disabled by default. You shouldn't use early access features in production
because they might cause performance or stability issues. Early access features
can be mostly feature-complete, but require further internal testing and remain
in the early access stage for at least one month.

Coder may make significant changes or revert features to a feature flag at any
time.

If you plan to activate an early access feature, we suggest that you use a
staging deployment.

<details><summary>To enable early access features:</summary>

Use the [Coder CLI](../install/cli.md) `--experiments` flag to enable early
access features:

- Enable all early access features:

  ```sh
  coder server --experiments=*
  ```

- Enable multiple early access features:

  ```sh
  coder server --experiments=feature1,feature2
  ```

You can also use the `CODER_EXPERIMENTS`
[environment variable](../admin/setup/index.md).

You can opt-out of a feature after you've enabled it.

</details>

### Target experiments at runtime

Some early access features accept runtime rules.
A rule turns the experiment on or off for every user, or targets it to some users, without a restart.
Only user-scoped experiments accept rules.
Other experiments, such as `no_nats_pubsub` or `workspace-capable-licensing`, read only the startup `--experiments` list and need a restart to change.

> [!NOTE]
> The rules API and the hidden `coder exp experiment-rules` command are experimental.
> They can change or be removed without notice.
> There is no UI editor yet.

You need the Owner role to change a rule.
The Auditor role can list rules.

Run `coder exp experiment-rules list` to show each user-scoped experiment, its startup default, and its rule.
The list also shows stored rules that target other experiments as `ignored`, because they have no effect.

#### Rule modes

Each user-scoped experiment has at most one rule:

| Rule                  | Effect                                                                     | Command                                                   |
|-----------------------|----------------------------------------------------------------------------|-----------------------------------------------------------|
| No rule, or `inherit` | Uses the startup `--experiments` default                                   | `coder exp experiment-rules reset <experiment>`           |
| `on`                  | On for every user                                                          | `coder exp experiment-rules on <experiment>`              |
| `off`                 | Off for every user, even if the experiment is enabled at startup           | `coder exp experiment-rules off <experiment>`             |
| `condition`           | On for users whose [CEL](https://cel.dev) condition is true, off otherwise | `coder exp experiment-rules set <experiment> <condition>` |

For example, to turn on an experiment for users in one group, widen it to every member of the `coder` organization, and then turn it off for everyone:

```sh
coder exp experiment-rules set mcp-tool-search '"coder/beta-testers" in user.groups'
coder exp experiment-rules set mcp-tool-search '"coder/Everyone" in user.groups'
coder exp experiment-rules off mcp-tool-search
```

Reset doesn't turn an experiment off.
It restores the startup default, which can enable the experiment for every user.
The command prints a warning when that happens.
To turn an experiment off for everyone, use `off`.

Each change increases the rule's revision.
Changing commands accept `--expected-revision` and fail when the stored rule has a different revision.
Without the flag, the command reads the current revision and writes against it, which protects only against a change made between that read and the write.
The command never retries a conflict: it prints the current rule and exits with an error.

If you use [audit logs](../admin/security/audit-logs.md), each change creates an entry with the `experiment_rule` resource type.
The entry records who changed the rule, when, and the old and new condition.
Audit lines in the server log carry the same diff.

#### Condition variables

A condition is a CEL expression that returns a boolean.
It can read one variable, `user`, with these fields:

| Field                | Type         | Value                                                                                                             |
|----------------------|--------------|-------------------------------------------------------------------------------------------------------------------|
| `user.id`            | string       | The user's ID                                                                                                     |
| `user.username`      | string       | The user's username                                                                                               |
| `user.email`         | string       | The user's email address, compared case-sensitively                                                               |
| `user.roles`         | list(string) | The user's explicit site roles, such as `owner`. The implied member role and organization roles are not included. |
| `user.organizations` | list(string) | Names of the organizations the user belongs to                                                                    |
| `user.groups`        | list(string) | Groups the user belongs to, as `<organization>/<group>`, including `<organization>/Everyone`                      |

A condition can be at most 4,096 characters long, and each evaluation has a CEL cost limit of 10,000.
Coder rejects a condition that fails to compile and returns the error to the person who wrote it.
Log lines about a failed condition record only the experiment, the rule revision, the error category, and the line and column, never the condition text.

#### When a change takes effect

On supporting replicas, a fresh authoritative database read after the update commits observes the new rule.
In-flight evaluations and work already using an earlier decision are not cancelled.
All serving replicas must run a supporting version before you rely on this control.

Replicas that run an earlier version ignore rules and use their startup `--experiments` list.
Every replica also falls back to its own startup list for experiments without a rule or with `inherit`, so give all replicas the same `--experiments` value.

The dashboard fetches the enabled experiments again when a page loads, when the browser window regains focus, and when the connection is restored, if its copy is more than 60 seconds old.
It doesn't refresh on a timer, so a tab that stays focused can show an out-of-date view.
The server applies the current rule to each request regardless of what the dashboard shows.

#### Failure behavior

If Coder can't read the rules, a stored rule is malformed, or a condition fails to compile or evaluate, the experiment is off for that decision, even if it is enabled at startup.
You can't change this behavior.

Rules gate features; they are not an authorization boundary.
Don't use a rule to restrict access to data or actions.

## Beta

- **Stable**: No
- **Production-ready**: Not fully
- **Support**: Documentation, [Discord](https://discord.gg/coder), and
  [GitHub issues](https://github.com/coder/coder/issues)

Beta features are open to the public and are tagged with a `Beta` label.

They’re in active development and subject to minor changes. They might contain
minor bugs, but are generally ready for use.

Beta features are often ready for general availability within two-three
releases. You should test beta features in staging environments. You can use
beta features in production, but should set expectations and inform users that
some features may be incomplete.

We keep documentation about beta features up-to-date with the latest
information, including planned features, limitations, and workarounds. If you
encounter an issue, please contact your
[Coder account team](https://coder.com/contact), reach out on
[Discord](https://discord.gg/coder), or create a
[GitHub issues](https://github.com/coder/coder/issues) if there isn't one
already. While we will do our best to provide support with beta features, most
issues will be escalated to the product team. Beta features are not covered
within service-level agreements (SLA).

Most beta features are enabled by default. Beta features are announced through
the [Coder Changelog](https://coder.com/changelog), and more information is
available in the documentation.

## General Availability (GA)

- **Stable**: Yes
- **Production-ready**: Yes
- **Support**: Yes, [based on license](https://coder.com/pricing).

All features that are not explicitly tagged as `Early access` or `Beta` are considered generally available (GA).
They have been tested, are stable, and are enabled by default.

If your Coder license includes an SLA, please consult it for an outline of
specific expectations.

For support, consult our knowledgeable and growing community on
[Discord](https://discord.gg/coder), or create a
[GitHub issue](https://github.com/coder/coder/issues) if one doesn't exist
already. Customers with a valid Coder license, can submit a support request or
contact your [account team](https://coder.com/contact).

We intend [Coder documentation](https://github.com/coder/coder/blob/main/contributing/documentation.md) to be the
[single source of truth](https://en.wikipedia.org/wiki/Single_source_of_truth)
and all features should have some form of complete documentation that outlines
how to use or implement a feature. If you discover an error or if you have a
suggestion that could improve the documentation, please
[submit a GitHub issue](https://github.com/coder/internal/issues/new?title=request%28docs%29%3A+request+title+here&labels=["customer-feedback","docs"]&body=please+enter+your+request+here).

Some GA features can be disabled for air-gapped deployments. Consult the
feature's documentation or submit a support ticket for assistance.

---

# REST API

Source: https://coder.com/docs/reference/api

<!-- DO NOT EDIT | GENERATED CONTENT -->

Get started with the Coder API:

## Quickstart

Generate a token on your Coder deployment by visiting:

````txt
https://coder.example.com/settings/tokens
````

List your workspaces

````sh
# CLI
curl https://coder.example.com/api/v2/workspaces?q=owner:me \
-H "Coder-Session-Token: <your-token>"
````

## Use cases

See some common [use cases](../../reference/index.md#use-cases) for the REST API.

## Request size limits

An endpoint that accepts a request body reads at most 4 MiB of it, unless it
sets a limit of its own.
An endpoint that sets its own limit declares `413` in this reference and
names the limit in the description, so the per-endpoint page is where to look
one up. A few endpoints answer `413` for a reason other than the size of
the request body, and their descriptions say so.

A body that exceeds the limit that applies to it is answered with
`413 Payload Too Large`, and the response names the limit it exceeded:

````json
{
  "message": "Request body too large.",
  "detail": "Maximum request body size is 4194304 bytes."
}
````

The limits are fixed. There is no deployment option that raises them.

## Sections

<children>
  This page is rendered on https://coder.com/docs/reference/api. Refer to the other documents in the `api/` directory.
</children>

---

# General

Source: https://coder.com/docs/reference/api/general

<!-- DO NOT EDIT | GENERATED CONTENT -->

## API root handler

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ \
  -H 'Accept: application/json'
```

`GET /api/v2/`

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

## Build info

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/buildinfo \
  -H 'Accept: application/json'
```

`GET /api/v2/buildinfo`

### Example responses

> 200 Response

```json
{
  "agent_api_version": "string",
  "dashboard_url": "string",
  "deployment_id": "string",
  "external_url": "string",
  "oauth2_provider": true,
  "provisioner_api_version": "string",
  "telemetry": true,
  "upgrade_message": "string",
  "version": "string",
  "webpush_public_key": "string",
  "workspace_proxy": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.BuildInfoResponse](schemas.md#codersdkbuildinforesponse) |

## Report CSP violations

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/csp/reports \
  -H 'Content-Type: application/json' \
  -H 'Accept: */*' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/csp/reports`

> Body parameter

```json
{
  "csp-report": {}
}
```

### Parameters

| Name   | In   | Type                                                 | Required | Description      |
|--------|------|------------------------------------------------------|----------|------------------|
| `body` | body | [coderd.cspViolation](schemas.md#coderdcspviolation) | true     | Violation report |

### Example responses

> 413 Response

### Responses

| Status | Meaning                                                                 | Description                 | Schema                                           |
|--------|-------------------------------------------------------------------------|-----------------------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                 | OK                          |                                                  |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 64 KiB | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get deployment config

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/deployment/config \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/deployment/config`

### Example responses

> 200 Response

```json
{
  "config": {
    "access_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "additional_csp_policy": [
      "string"
    ],
    "address": {
      "host": "string",
      "port": "string"
    },
    "agent_fallback_troubleshooting_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "agent_stat_refresh_interval": 0,
    "ai": {
      "aibridge_proxy": {
        "allowed_private_cidrs": [
          "string"
        ],
        "api_dump_dir": "string",
        "cert_file": "string",
        "domain_allowlist": [
          "string"
        ],
        "enabled": true,
        "key_file": "string",
        "listen_addr": "string",
        "target": "string",
        "tls_cert_file": "string",
        "tls_key_file": "string",
        "upstream_proxy": "string",
        "upstream_proxy_ca": "string"
      },
      "bridge": {
        "actor_header_email": "string",
        "actor_header_id": "string",
        "actor_header_username": "string",
        "allow_byok": true,
        "api_dump_dir": "string",
        "budget_period": "string",
        "budget_policy": "string",
        "circuit_breaker_enabled": true,
        "circuit_breaker_failure_threshold": 0,
        "circuit_breaker_interval": 0,
        "circuit_breaker_max_requests": 0,
        "circuit_breaker_timeout": 0,
        "disable_content_recording": true,
        "enabled": true,
        "inject_coder_mcp_tools": true,
        "max_concurrency": 0,
        "rate_limit": 0,
        "retention": 0,
        "send_actor_headers": true,
        "structured_logging": true,
        "structured_logging_source": "string"
      },
      "chat": {
        "acquire_batch_size": 0,
        "debug_logging_enabled": true,
        "hook_allow_insecure": true,
        "hook_enabled": true,
        "hook_secret": "string",
        "hook_timeout": 0,
        "hook_url": {
          "forceQuery": true,
          "fragment": "string",
          "host": "string",
          "omitHost": true,
          "opaque": "string",
          "path": "string",
          "rawFragment": "string",
          "rawPath": "string",
          "rawQuery": "string",
          "scheme": "string",
          "user": {}
        },
        "max_attachments_per_chat": 0,
        "max_concurrent_recording_uploads": 0,
        "max_generation_retries": 0,
        "max_prompt_bytes": 0,
        "max_queued_messages_per_chat": 0,
        "max_steps_per_turn": 0,
        "stream_silence_timeout": 0
      }
    },
    "allow_workspace_renames": true,
    "autobuild_poll_interval": 0,
    "browser_only": true,
    "cache_directory": "string",
    "cli_upgrade_message": "string",
    "cluster": {
      "host": "string"
    },
    "config": "string",
    "config_ssh": {
      "deploymentName": "string",
      "sshconfigOptions": [
        "string"
      ]
    },
    "dangerous": {
      "allow_all_cors": true,
      "allow_path_app_sharing": true,
      "allow_path_app_site_owner_access": true
    },
    "derp": {
      "config": {
        "block_direct": true,
        "force_websockets": true,
        "path": "string",
        "url": "string"
      },
      "server": {
        "enable": true,
        "region_code": "string",
        "region_id": 0,
        "region_name": "string",
        "relay_url": {
          "forceQuery": true,
          "fragment": "string",
          "host": "string",
          "omitHost": true,
          "opaque": "string",
          "path": "string",
          "rawFragment": "string",
          "rawPath": "string",
          "rawQuery": "string",
          "scheme": "string",
          "user": {}
        },
        "stun_addresses": [
          "string"
        ]
      }
    },
    "disable_chat_caller_supplied_tools": true,
    "disable_chat_sharing": true,
    "disable_owner_workspace_exec": true,
    "disable_password_auth": true,
    "disable_path_apps": true,
    "disable_user_secret_file_path": true,
    "disable_workspace_agent_context_sync": true,
    "disable_workspace_sharing": true,
    "docs_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "dynamic_parameters_full_evaluation": true,
    "enable_authz_recording": true,
    "enable_terraform_debug_mode": true,
    "ephemeral_deployment": true,
    "experiments": [
      "string"
    ],
    "external_auth": {
      "value": [
        {
          "api_base_url": "string",
          "app_install_url": "string",
          "app_installations_url": "string",
          "auth_url": "string",
          "client_id": "string",
          "code_challenge_methods_supported": [
            "string"
          ],
          "device_code_url": "string",
          "device_flow": true,
          "display_icon": "string",
          "display_name": "string",
          "id": "string",
          "mcp_tool_allow_regex": "string",
          "mcp_tool_deny_regex": "string",
          "mcp_url": "string",
          "no_refresh": true,
          "redirect_url": "string",
          "regex": "string",
          "revoke_url": "string",
          "scopes": [
            "string"
          ],
          "token_url": "string",
          "type": "string",
          "validate_url": "string"
        }
      ]
    },
    "external_auth_github_default_provider_enable": true,
    "external_token_encryption_keys": [
      "string"
    ],
    "healthcheck": {
      "refresh": 0,
      "threshold_database": 0
    },
    "http_address": "string",
    "http_cookies": {
      "host_prefix": true,
      "same_site": "string",
      "secure_auth_cookie": true
    },
    "job_hang_detector_interval": 0,
    "logging": {
      "human": "string",
      "json": "string",
      "log_filter": [
        "string"
      ],
      "stackdriver": "string"
    },
    "mcp_allowed_private_cidrs": [
      "string"
    ],
    "metrics_cache_refresh_interval": 0,
    "notifications": {
      "dispatch_timeout": 0,
      "email": {
        "auth": {
          "identity": "string",
          "password": "string",
          "password_file": "string",
          "username": "string"
        },
        "force_tls": true,
        "from": "string",
        "hello": "string",
        "smarthost": "string",
        "tls": {
          "ca_file": "string",
          "cert_file": "string",
          "insecure_skip_verify": true,
          "key_file": "string",
          "server_name": "string",
          "start_tls": true
        }
      },
      "fetch_interval": 0,
      "inbox": {
        "enabled": true
      },
      "lease_count": 0,
      "lease_period": 0,
      "max_send_attempts": 0,
      "method": "string",
      "retry_interval": 0,
      "sync_buffer_size": 0,
      "sync_interval": 0,
      "webhook": {
        "endpoint": {
          "forceQuery": true,
          "fragment": "string",
          "host": "string",
          "omitHost": true,
          "opaque": "string",
          "path": "string",
          "rawFragment": "string",
          "rawPath": "string",
          "rawQuery": "string",
          "scheme": "string",
          "user": {}
        }
      }
    },
    "oauth2": {
      "github": {
        "allow_everyone": true,
        "allow_signups": true,
        "allowed_orgs": [
          "string"
        ],
        "allowed_teams": [
          "string"
        ],
        "client_id": "string",
        "client_secret": "string",
        "default_provider_enable": true,
        "device_flow": true,
        "enterprise_base_url": "string"
      },
      "provider": {
        "enable": true
      }
    },
    "oidc": {
      "allow_signups": true,
      "auth_url_params": {},
      "auto_repair_links": true,
      "client_cert_file": "string",
      "client_id": "string",
      "client_key_file": "string",
      "client_secret": "string",
      "email_domain": [
        "string"
      ],
      "email_fallback": true,
      "email_field": "string",
      "group_allow_list": [
        "string"
      ],
      "group_auto_create": true,
      "group_mapping": {},
      "group_regex_filter": {},
      "groups_field": "string",
      "icon_url": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      },
      "ignore_email_verified": true,
      "ignore_user_info": true,
      "issuer_url": "string",
      "name_field": "string",
      "organization_assign_default": true,
      "organization_field": "string",
      "organization_mapping": {},
      "redirect_allowed_hosts": [
        "string"
      ],
      "redirect_url": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      },
      "scopes": [
        "string"
      ],
      "sign_in_text": "string",
      "signups_disabled_text": "string",
      "skip_issuer_checks": true,
      "source_user_info_from_access_token": true,
      "user_role_field": "string",
      "user_role_mapping": {},
      "user_roles_default": [
        "string"
      ],
      "username_field": "string"
    },
    "pg_auth": "string",
    "pg_conn_max_idle": "string",
    "pg_conn_max_open": 0,
    "pg_connection_url": "string",
    "pprof": {
      "address": {
        "host": "string",
        "port": "string"
      },
      "enable": true
    },
    "prometheus": {
      "address": {
        "host": "string",
        "port": "string"
      },
      "aggregate_agent_stats_by": [
        "string"
      ],
      "collect_agent_stats": true,
      "collect_db_metrics": true,
      "enable": true
    },
    "provisioner": {
      "daemon_poll_interval": 0,
      "daemon_poll_jitter": 0,
      "daemon_psk": "string",
      "daemon_types": [
        "string"
      ],
      "daemons": 0,
      "disable_module_cache": true,
      "force_cancel_interval": 0
    },
    "proxy_health_status_interval": 0,
    "proxy_trusted_headers": [
      "string"
    ],
    "proxy_trusted_origins": [
      "string"
    ],
    "rate_limit": {
      "api": 0,
      "disable_all": true
    },
    "redirect_to_access_url": true,
    "retention": {
      "api_keys": 0,
      "audit_logs": 0,
      "boundary_logs": 0,
      "connection_logs": 0,
      "workspace_agent_logs": 0
    },
    "scim_api_key": "string",
    "scim_use_legacy": true,
    "session_lifetime": {
      "default_duration": 0,
      "default_token_lifetime": 0,
      "disable_expiry_refresh": true,
      "max_admin_token_lifetime": 0,
      "max_token_lifetime": 0,
      "refresh_default_duration": 0
    },
    "ssh_keygen_algorithm": "string",
    "stats_collection": {
      "usage_stats": {
        "enable": true
      }
    },
    "strict_transport_security": 0,
    "strict_transport_security_options": [
      "string"
    ],
    "support": {
      "links": {
        "value": [
          {
            "icon": "bug",
            "location": "navbar",
            "name": "string",
            "target": "string"
          }
        ]
      }
    },
    "swagger": {
      "enable": true
    },
    "telemetry": {
      "enable": true,
      "trace": true,
      "url": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      }
    },
    "template_builder": {
      "disabled": true,
      "registry_url": "string"
    },
    "terms_of_service_url": "string",
    "tls": {
      "address": {
        "host": "string",
        "port": "string"
      },
      "allow_insecure_ciphers": true,
      "cert_file": [
        "string"
      ],
      "client_auth": "string",
      "client_ca_file": "string",
      "client_cert_file": "string",
      "client_key_file": "string",
      "enable": true,
      "key_file": [
        "string"
      ],
      "min_version": "string",
      "redirect_http": true,
      "supported_ciphers": [
        "string"
      ]
    },
    "trace": {
      "capture_logs": true,
      "data_dog": true,
      "enable": true,
      "honeycomb_api_key": "string"
    },
    "update_check": true,
    "user_quiet_hours_schedule": {
      "allow_user_custom": true,
      "default_schedule": "string"
    },
    "verbose": true,
    "web_terminal_renderer": "string",
    "wgtunnel_host": "string",
    "wildcard_access_url": "string",
    "workspace_hostname_suffix": "string",
    "workspace_prebuilds": {
      "failure_hard_limit": 0,
      "reconciliation_backoff_interval": 0,
      "reconciliation_backoff_lookback": 0,
      "reconciliation_interval": 0
    },
    "write_config": true
  },
  "options": [
    {
      "annotations": {
        "property1": "string",
        "property2": "string"
      },
      "default": "string",
      "description": "string",
      "env": "string",
      "flag": "string",
      "flag_shorthand": "string",
      "group": {
        "description": "string",
        "name": "string",
        "parent": {
          "description": "string",
          "name": "string",
          "parent": {},
          "yaml": "string"
        },
        "yaml": "string"
      },
      "hidden": true,
      "name": "string",
      "required": true,
      "use_instead": [
        {}
      ],
      "value": null,
      "value_source": "",
      "yaml": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.DeploymentConfig](schemas.md#codersdkdeploymentconfig) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## SSH Config

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/deployment/ssh \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/deployment/ssh`

### Example responses

> 200 Response

```json
{
  "hostname_prefix": "string",
  "hostname_suffix": "string",
  "ssh_config_options": {
    "property1": "string",
    "property2": "string"
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.SSHConfigResponse](schemas.md#codersdksshconfigresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get deployment stats

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/deployment/stats \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/deployment/stats`

### Example responses

> 200 Response

```json
{
  "aggregated_from": "2019-08-24T14:15:22Z",
  "collected_at": "2019-08-24T14:15:22Z",
  "next_update_at": "2019-08-24T14:15:22Z",
  "session_count": {
    "apps": {
      "property1": {
        "count": 0,
        "display_name": "string",
        "family": "vscode",
        "icon": "string"
      },
      "property2": {
        "count": 0,
        "display_name": "string",
        "family": "vscode",
        "icon": "string"
      }
    },
    "jetbrains": 0,
    "reconnecting_pty": 0,
    "ssh": 0,
    "vscode": 0
  },
  "workspaces": {
    "building": 0,
    "connection_latency_ms": {
      "p50": 0,
      "p95": 0
    },
    "failed": 0,
    "pending": 0,
    "running": 0,
    "rx_bytes": 0,
    "stopped": 0,
    "tx_bytes": 0
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                         |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.DeploymentStats](schemas.md#codersdkdeploymentstats) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user secrets capabilities

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/deployment/user-secrets/capabilities \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/deployment/user-secrets/capabilities`

### Example responses

> 200 Response

```json
{
  "file_path_delivery_enabled": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                         |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserSecretsCapabilities](schemas.md#codersdkusersecretscapabilities) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get enabled experiments

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/experiments \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/experiments`

### Example responses

> 200 Response

```json
[
  "example"
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                        |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Experiment](schemas.md#codersdkexperiment) |

<h3 id="get-enabled-experiments-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type  | Required | Restrictions | Description |
|----------------|-------|----------|--------------|-------------|
| `[array item]` | array | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get safe experiments

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/experiments/available \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/experiments/available`

### Example responses

> 200 Response

```json
[
  "example"
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                        |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Experiment](schemas.md#codersdkexperiment) |

<h3 id="get-safe-experiments-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type  | Required | Restrictions | Description |
|----------------|-------|----------|--------------|-------------|
| `[array item]` | array | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update check

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/updatecheck \
  -H 'Accept: application/json'
```

`GET /api/v2/updatecheck`

### Example responses

> 200 Response

```json
{
  "current": true,
  "url": "string",
  "version": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                 |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UpdateCheckResponse](schemas.md#codersdkupdatecheckresponse) |

## Get token config

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/keys/tokens/tokenconfig \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/keys/tokens/tokenconfig`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "max_token_lifetime": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                 |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.TokenConfig](schemas.md#codersdktokenconfig) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# AI Gateway

Source: https://coder.com/docs/reference/api/aigateway

<!-- DO NOT EDIT | GENERATED CONTENT -->

## List AI Gateway clients

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai-gateway/clients \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/ai-gateway/clients`

Alias: also available at /api/v2/aibridge/clients for backward compatibility.

### Example responses

> 200 Response

```json
[
  "string"
]
```

### Responses

| Status | Meaning                                                 | Description | Schema          |
|--------|---------------------------------------------------------|-------------|-----------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of string |

<h3 id="list-ai-gateway-clients-responseschema">Response Schema</h3>

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List AI Gateway models

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai-gateway/models \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/ai-gateway/models`

Alias: also available at /api/v2/aibridge/models for backward compatibility.

### Parameters

| Name    | In    | Type   | Required | Description                                                                                              |
|---------|-------|--------|----------|----------------------------------------------------------------------------------------------------------|
| `q`     | query | string | false    | Search query in the format `key:value`. Available keys are: model. A bare term searches by model prefix. |
| `model` | query | string | false    | Literal model identifier prefix. Cannot be combined with q.                                              |

### Example responses

> 200 Response

```json
[
  "string"
]
```

### Responses

| Status | Meaning                                                 | Description | Schema          |
|--------|---------------------------------------------------------|-------------|-----------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of string |

<h3 id="list-ai-gateway-models-responseschema">Response Schema</h3>

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List AI Gateway providers

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai-gateway/providers \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/ai-gateway/providers`

### Example responses

> 200 Response

```json
[
  {
    "display_name": "string",
    "icon": "string",
    "name": "string",
    "type": "openai"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                    |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.AIBridgeProvider](schemas.md#codersdkaibridgeprovider) |

<h3 id="list-ai-gateway-providers-responseschema">Response Schema</h3>

Status Code **200**

| Name             | Type                                                         | Required | Restrictions | Description |
|------------------|--------------------------------------------------------------|----------|--------------|-------------|
| `[array item]`   | array                                                        | false    |              |             |
| `» display_name` | string                                                       | false    |              |             |
| `» icon`         | string                                                       | false    |              |             |
| `» name`         | string                                                       | false    |              |             |
| `» type`         | [codersdk.AIProviderType](schemas.md#codersdkaiprovidertype) | false    |              |             |

#### Enumerated Values

| Property | Value(s)                                                                                                |
|----------|---------------------------------------------------------------------------------------------------------|
| `type`   | `anthropic`, `azure`, `bedrock`, `copilot`, `google`, `openai`, `openai-compat`, `openrouter`, `vercel` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List AI Gateway sessions

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai-gateway/sessions \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/ai-gateway/sessions`

Alias: also available at /api/v2/aibridge/sessions for backward compatibility.

### Parameters

| Name               | In    | Type    | Required | Description                                                                                                                                               |
|--------------------|-------|---------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
| `q`                | query | string  | false    | Search query in the format `key:value`. Available keys are: initiator, provider, provider_name, model, client, session_id, started_after, started_before. |
| `limit`            | query | integer | false    | Page limit                                                                                                                                                |
| `after_session_id` | query | string  | false    | Cursor pagination after session ID (cannot be used with offset)                                                                                           |
| `offset`           | query | integer | false    | Offset pagination (cannot be used with after_session_id)                                                                                                  |

### Example responses

> 200 Response

```json
{
  "count": 0,
  "sessions": [
    {
      "client": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "id": "string",
      "initiator": {
        "avatar_url": "http://example.com",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string",
        "username": "string"
      },
      "last_active_at": "2019-08-24T14:15:22Z",
      "last_prompt": "string",
      "metadata": {
        "property1": null,
        "property2": null
      },
      "models": [
        "string"
      ],
      "network_calls": {
        "blocked": 0,
        "total": 0
      },
      "providers": [
        "string"
      ],
      "started_at": "2019-08-24T14:15:22Z",
      "threads": 0,
      "token_usage_summary": {
        "cache_read_input_tokens": 0,
        "cache_write_input_tokens": 0,
        "input_tokens": 0,
        "output_tokens": 0
      }
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AIBridgeListSessionsResponse](schemas.md#codersdkaibridgelistsessionsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get AI Gateway session threads

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai-gateway/sessions/{session_id} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/ai-gateway/sessions/{session_id}`

Alias: also available at /api/v2/aibridge/sessions/{session_id} for backward compatibility.

### Parameters

| Name         | In    | Type    | Required | Description                                         |
|--------------|-------|---------|----------|-----------------------------------------------------|
| `session_id` | path  | string  | true     | Session ID (client_session_id or interception UUID) |
| `after_id`   | query | string  | false    | Thread pagination cursor (forward/older)            |
| `before_id`  | query | string  | false    | Thread pagination cursor (backward/newer)           |
| `limit`      | query | integer | false    | Number of threads per page (default 50)             |

### Example responses

> 200 Response

```json
{
  "client": "string",
  "ended_at": "2019-08-24T14:15:22Z",
  "id": "string",
  "initiator": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "metadata": {
    "property1": null,
    "property2": null
  },
  "models": [
    "string"
  ],
  "network_call_logs": [
    {
      "allowed": true,
      "captured_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "detail": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "matched_rule": "string",
      "method": "string",
      "proto": "string",
      "sequence_number": 0,
      "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82"
    }
  ],
  "network_calls": {
    "blocked": 0,
    "total": 0
  },
  "network_domain_count": 0,
  "network_top_domains": [
    {
      "count": 0,
      "domain": "string"
    }
  ],
  "page_ended_at": "2019-08-24T14:15:22Z",
  "page_started_at": "2019-08-24T14:15:22Z",
  "providers": [
    "string"
  ],
  "started_at": "2019-08-24T14:15:22Z",
  "threads": [
    {
      "agent_firewall_sequence_number": 0,
      "agent_firewall_session_id": "3735294f-18b1-4e7a-a269-99c30f0b30e7",
      "agentic_actions": [
        {
          "attribution": {
            "property1": "string",
            "property2": "string"
          },
          "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
          "model": "string",
          "thinking": [
            {
              "text": "string"
            }
          ],
          "token_usage": {
            "cache_read_input_tokens": 0,
            "cache_write_input_tokens": 0,
            "input_tokens": 0,
            "metadata": {
              "property1": null,
              "property2": null
            },
            "output_tokens": 0
          },
          "tool_calls": [
            {
              "created_at": "2019-08-24T14:15:22Z",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "injected": true,
              "input": "string",
              "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
              "metadata": {
                "property1": null,
                "property2": null
              },
              "provider_response_id": "string",
              "server_url": "string",
              "tool": "string"
            }
          ]
        }
      ],
      "attribution": {
        "property1": "string",
        "property2": "string"
      },
      "credential_hint": "string",
      "credential_kind": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "error_message": "string",
      "error_type": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "model": "string",
      "prompt": "string",
      "provider": "string",
      "started_at": "2019-08-24T14:15:22Z",
      "token_usage": {
        "cache_read_input_tokens": 0,
        "cache_write_input_tokens": 0,
        "input_tokens": 0,
        "metadata": {
          "property1": null,
          "property2": null
        },
        "output_tokens": 0
      }
    }
  ],
  "token_usage_summary": {
    "cache_read_input_tokens": 0,
    "cache_write_input_tokens": 0,
    "input_tokens": 0,
    "metadata": {
      "property1": null,
      "property2": null
    },
    "output_tokens": 0
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AIBridgeSessionThreadsResponse](schemas.md#codersdkaibridgesessionthreadsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# AI Providers

Source: https://coder.com/docs/reference/api/aiproviders

<!-- DO NOT EDIT | GENERATED CONTENT -->

## List AI providers

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai/providers \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/ai/providers`

### Example responses

> 200 Response

```json
[
  {
    "api_keys": [
      {
        "created_at": "2019-08-24T14:15:22Z",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "masked": "string"
      }
    ],
    "base_url": "string",
    "created_at": "2019-08-24T14:15:22Z",
    "display_name": "string",
    "enabled": true,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "settings": {},
    "status": {
      "warnings": [
        "string"
      ]
    },
    "type": "openai",
    "updated_at": "2019-08-24T14:15:22Z"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                        |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.AIProvider](schemas.md#codersdkaiprovider) |

<h3 id="list-ai-providers-responseschema">Response Schema</h3>

Status Code **200**

| Name             | Type                                                                 | Required | Restrictions | Description                                            |
|------------------|----------------------------------------------------------------------|----------|--------------|--------------------------------------------------------|
| `[array item]`   | array                                                                | false    |              |                                                        |
| `» api_keys`     | array                                                                | false    |              |                                                        |
| `»» created_at`  | string(date-time)                                                    | false    |              |                                                        |
| `»» id`          | string(uuid)                                                         | false    |              |                                                        |
| `»» masked`      | string                                                               | false    |              |                                                        |
| `» base_url`     | string                                                               | false    |              |                                                        |
| `» created_at`   | string(date-time)                                                    | false    |              |                                                        |
| `» display_name` | string                                                               | false    |              |                                                        |
| `» enabled`      | boolean                                                              | false    |              |                                                        |
| `» icon`         | string                                                               | false    |              |                                                        |
| `» id`           | string(uuid)                                                         | false    |              |                                                        |
| `» name`         | string                                                               | false    |              |                                                        |
| `» settings`     | [codersdk.AIProviderSettings](schemas.md#codersdkaiprovidersettings) | false    |              |                                                        |
| `» status`       | [codersdk.AIProviderStatus](schemas.md#codersdkaiproviderstatus)     | false    |              | Status carries runtime routing status; nil when empty. |
| `»» warnings`    | array                                                                | false    |              |                                                        |
| `» type`         | [codersdk.AIProviderType](schemas.md#codersdkaiprovidertype)         | false    |              |                                                        |
| `» updated_at`   | string(date-time)                                                    | false    |              |                                                        |

#### Enumerated Values

| Property | Value(s)                                                                                                |
|----------|---------------------------------------------------------------------------------------------------------|
| `type`   | `anthropic`, `azure`, `bedrock`, `copilot`, `google`, `openai`, `openai-compat`, `openrouter`, `vercel` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create an AI provider

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/ai/providers \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/ai/providers`

> Body parameter

```json
{
  "api_keys": [
    "string"
  ],
  "base_url": "string",
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "name": "string",
  "settings": {},
  "type": "openai"
}
```

### Parameters

| Name   | In   | Type                                                                           | Required | Description                |
|--------|------|--------------------------------------------------------------------------------|----------|----------------------------|
| `body` | body | [codersdk.CreateAIProviderRequest](schemas.md#codersdkcreateaiproviderrequest) | true     | Create AI provider request |

### Example responses

> 201 Response

```json
{
  "api_keys": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "masked": "string"
    }
  ],
  "base_url": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "settings": {},
  "status": {
    "warnings": [
      "string"
    ]
  },
  "type": "openai",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                               |
|--------|--------------------------------------------------------------|-------------|------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.AIProvider](schemas.md#codersdkaiprovider) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get an AI provider

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai/providers/{idOrName} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/ai/providers/{idOrName}`

### Parameters

| Name       | In   | Type   | Required | Description         |
|------------|------|--------|----------|---------------------|
| `idOrName` | path | string | true     | Provider ID or name |

### Example responses

> 200 Response

```json
{
  "api_keys": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "masked": "string"
    }
  ],
  "base_url": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "settings": {},
  "status": {
    "warnings": [
      "string"
    ]
  },
  "type": "openai",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                               |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AIProvider](schemas.md#codersdkaiprovider) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete an AI provider

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/ai/providers/{idOrName} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/ai/providers/{idOrName}`

### Parameters

| Name       | In   | Type   | Required | Description         |
|------------|------|--------|----------|---------------------|
| `idOrName` | path | string | true     | Provider ID or name |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update an AI provider

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/ai/providers/{idOrName} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/ai/providers/{idOrName}`

> Body parameter

```json
{
  "api_keys": [
    {
      "api_key": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    }
  ],
  "base_url": "string",
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "settings": {}
}
```

### Parameters

| Name       | In   | Type                                                                           | Required | Description                |
|------------|------|--------------------------------------------------------------------------------|----------|----------------------------|
| `idOrName` | path | string                                                                         | true     | Provider ID or name        |
| `body`     | body | [codersdk.UpdateAIProviderRequest](schemas.md#codersdkupdateaiproviderrequest) | true     | Update AI provider request |

### Example responses

> 200 Response

```json
{
  "api_keys": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "masked": "string"
    }
  ],
  "base_url": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "settings": {},
  "status": {
    "warnings": [
      "string"
    ]
  },
  "type": "openai",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                               |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AIProvider](schemas.md#codersdkaiprovider) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Agents

Source: https://coder.com/docs/reference/api/agents

<!-- DO NOT EDIT | GENERATED CONTENT -->

Workspace agent endpoints. These power the workspace agent daemon defined by the `coder_agent` Terraform resource. This API is NOT the Coder Agents Chats API. For programmatic access to AI Coder Agents, see the Chats API.

## Get DERP map updates

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/derp-map \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/derp-map`

### Responses

| Status | Meaning                                                                  | Description         | Schema |
|--------|--------------------------------------------------------------------------|---------------------|--------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## User-scoped tailnet RPC connection

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/tailnet \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/tailnet`

### Responses

| Status | Meaning                                                                  | Description         | Schema |
|--------|--------------------------------------------------------------------------|---------------------|--------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Authenticate agent on AWS instance

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaceagents/aws-instance-identity \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaceagents/aws-instance-identity`

> Body parameter

```json
{
  "agent_name": "string",
  "document": "string",
  "signature": "string"
}
```

### Parameters

| Name   | In   | Type                                                                             | Required | Description                                                                                                           |
|--------|------|----------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------|
| `body` | body | [agentsdk.AWSInstanceIdentityToken](schemas.md#agentsdkawsinstanceidentitytoken) | true     | Instance identity token. The optional agent_name field disambiguates when multiple agents share the same instance ID. |

### Example responses

> 200 Response

```json
{
  "session_token": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [agentsdk.AuthenticateResponse](schemas.md#agentsdkauthenticateresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Authenticate agent on Azure instance

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaceagents/azure-instance-identity \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaceagents/azure-instance-identity`

> Body parameter

```json
{
  "agent_name": "string",
  "encoding": "string",
  "signature": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                 | Required | Description                                                                                                           |
|--------|------|--------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------|
| `body` | body | [agentsdk.AzureInstanceIdentityToken](schemas.md#agentsdkazureinstanceidentitytoken) | true     | Instance identity token. The optional agent_name field disambiguates when multiple agents share the same instance ID. |

### Example responses

> 200 Response

```json
{
  "session_token": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [agentsdk.AuthenticateResponse](schemas.md#agentsdkauthenticateresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Authenticate agent on Google Cloud instance

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaceagents/google-instance-identity \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaceagents/google-instance-identity`

> Body parameter

```json
{
  "agent_name": "string",
  "json_web_token": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                   | Required | Description                                                                                                           |
|--------|------|----------------------------------------------------------------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------|
| `body` | body | [agentsdk.GoogleInstanceIdentityToken](schemas.md#agentsdkgoogleinstanceidentitytoken) | true     | Instance identity token. The optional agent_name field disambiguates when multiple agents share the same instance ID. |

### Example responses

> 200 Response

```json
{
  "session_token": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [agentsdk.AuthenticateResponse](schemas.md#agentsdkauthenticateresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Patch workspace agent app status

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/workspaceagents/me/app-status \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/workspaceagents/me/app-status`

> Body parameter

```json
{
  "app_slug": "string",
  "icon": "string",
  "message": "string",
  "needs_user_attention": true,
  "state": "working",
  "uri": "string"
}
```

### Parameters

| Name   | In   | Type                                                         | Required | Description |
|--------|------|--------------------------------------------------------------|----------|-------------|
| `body` | body | [agentsdk.PatchAppStatus](schemas.md#agentsdkpatchappstatus) | true     | app status  |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace agent external auth

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/me/external-auth?match=string&id=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/me/external-auth`

### Parameters

| Name     | In    | Type    | Required | Description                       |
|----------|-------|---------|----------|-----------------------------------|
| `match`  | query | string  | true     | Match                             |
| `id`     | query | string  | true     | Provider ID                       |
| `listen` | query | boolean | false    | Wait for a new token to be issued |

### Example responses

> 200 Response

```json
{
  "access_token": "string",
  "expires_at": "string",
  "password": "string",
  "token_extra": {},
  "type": "string",
  "url": "string",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [agentsdk.ExternalAuthResponse](schemas.md#agentsdkexternalauthresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Removed: Get workspace agent git auth

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/me/gitauth?match=string&id=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/me/gitauth`

### Parameters

| Name     | In    | Type    | Required | Description                       |
|----------|-------|---------|----------|-----------------------------------|
| `match`  | query | string  | true     | Match                             |
| `id`     | query | string  | true     | Provider ID                       |
| `listen` | query | boolean | false    | Wait for a new token to be issued |

### Example responses

> 200 Response

```json
{
  "access_token": "string",
  "expires_at": "string",
  "password": "string",
  "token_extra": {},
  "type": "string",
  "url": "string",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [agentsdk.ExternalAuthResponse](schemas.md#agentsdkexternalauthresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace agent Git SSH key

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/me/gitsshkey \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/me/gitsshkey`

### Example responses

> 200 Response

```json
{
  "private_key": "string",
  "public_key": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                             |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [agentsdk.GitSSHKey](schemas.md#agentsdkgitsshkey) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Post workspace agent log source

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaceagents/me/log-source \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaceagents/me/log-source`

> Body parameter

```json
{
  "display_name": "string",
  "icon": "string",
  "id": "string"
}
```

### Parameters

| Name   | In   | Type                                                                     | Required | Description        |
|--------|------|--------------------------------------------------------------------------|----------|--------------------|
| `body` | body | [agentsdk.PostLogSourceRequest](schemas.md#agentsdkpostlogsourcerequest) | true     | Log source request |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                         |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceAgentLogSource](schemas.md#codersdkworkspaceagentlogsource) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Patch workspace agent logs

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/workspaceagents/me/logs \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/workspaceagents/me/logs`

> Body parameter

```json
{
  "log_source_id": "string",
  "logs": [
    {
      "created_at": "string",
      "level": "trace",
      "output": "string"
    }
  ]
}
```

### Parameters

| Name   | In   | Type                                               | Required | Description |
|--------|------|----------------------------------------------------|----------|-------------|
| `body` | body | [agentsdk.PatchLogs](schemas.md#agentsdkpatchlogs) | true     | logs        |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                                 | Description                      | Schema                                           |
|--------|-------------------------------------------------------------------------|----------------------------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                 | OK                               | [codersdk.Response](schemas.md#codersdkresponse) |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Agent log storage limit exceeded | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace agent reinitialization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/me/reinit \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/me/reinit`

### Parameters

| Name   | In    | Type    | Required | Description                     |
|--------|-------|---------|----------|---------------------------------|
| `wait` | query | boolean | false    | Opt in to durable reinit checks |

### Example responses

> 200 Response

```json
{
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "reason": "prebuild_claimed",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                       | Description | Schema                                                                     |
|--------|---------------------------------------------------------------|-------------|----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)       | OK          | [agentsdk.ReinitializationEvent](schemas.md#agentsdkreinitializationevent) |
| 409    | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8) | Conflict    | [codersdk.Response](schemas.md#codersdkresponse)                           |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace agent by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspaceagent` | path | string(uuid) | true     | Workspace agent ID |

### Example responses

> 200 Response

```json
{
  "api_version": "string",
  "apps": [
    {
      "command": "string",
      "display_name": "string",
      "external": true,
      "group": "string",
      "health": "disabled",
      "healthcheck": {
        "interval": 0,
        "threshold": 0,
        "url": "string"
      },
      "hidden": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "open_in": "slim-window",
      "sharing_level": "owner",
      "slug": "string",
      "statuses": [
        {
          "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
          "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
          "created_at": "2019-08-24T14:15:22Z",
          "icon": "string",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "message": "string",
          "needs_user_attention": true,
          "state": "working",
          "uri": "string",
          "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
        }
      ],
      "subdomain": true,
      "subdomain_name": "string",
      "tooltip": "string",
      "url": "string"
    }
  ],
  "architecture": "string",
  "connection_timeout_seconds": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "directory": "string",
  "disconnected_at": "2019-08-24T14:15:22Z",
  "display_apps": [
    "vscode"
  ],
  "environment_variables": {
    "property1": "string",
    "property2": "string"
  },
  "expanded_directory": "string",
  "first_connected_at": "2019-08-24T14:15:22Z",
  "health": {
    "healthy": false,
    "reason": "agent has lost connection"
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "instance_id": "string",
  "last_connected_at": "2019-08-24T14:15:22Z",
  "latency": {
    "property1": {
      "latency_ms": 0,
      "preferred": true
    },
    "property2": {
      "latency_ms": 0,
      "preferred": true
    }
  },
  "lifecycle_state": "created",
  "log_sources": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "display_name": "string",
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
    }
  ],
  "logs_length": 0,
  "logs_overflowed": true,
  "metadata": [
    {
      "description": {
        "display_name": "string",
        "interval": 0,
        "key": "string",
        "script": "string",
        "timeout": 0
      },
      "result": {
        "age": 0,
        "collected_at": "2019-08-24T14:15:22Z",
        "error": "string",
        "value": "string"
      }
    }
  ],
  "name": "string",
  "operating_system": "string",
  "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
  "ready_at": "2019-08-24T14:15:22Z",
  "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
  "scripts": [
    {
      "cron": "string",
      "display_name": "string",
      "exit_code": 0,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "log_path": "string",
      "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
      "run_on_start": true,
      "run_on_stop": true,
      "script": "string",
      "start_blocks_login": true,
      "status": "ok",
      "timeout": 0
    }
  ],
  "started_at": "2019-08-24T14:15:22Z",
  "startup_script_behavior": "blocking",
  "status": "connecting",
  "subsystems": [
    "envbox"
  ],
  "troubleshooting_url": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "version": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceAgent](schemas.md#codersdkworkspaceagent) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get connection info for workspace agent

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/connection \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}/connection`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspaceagent` | path | string(uuid) | true     | Workspace agent ID |

### Example responses

> 200 Response

```json
{
  "derp_force_websockets": true,
  "derp_map": {
    "homeParams": {
      "regionScore": {
        "property1": 0,
        "property2": 0
      }
    },
    "omitDefaultRegions": true,
    "regions": {
      "property1": {
        "avoid": true,
        "embeddedRelay": true,
        "nodes": [
          {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          }
        ],
        "regionCode": "string",
        "regionID": 0,
        "regionName": "string"
      },
      "property2": {
        "avoid": true,
        "embeddedRelay": true,
        "nodes": [
          {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          }
        ],
        "regionCode": "string",
        "regionID": 0,
        "regionName": "string"
      }
    }
  },
  "disable_direct_connections": true,
  "hostname_suffix": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                         |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [workspacesdk.AgentConnectionInfo](schemas.md#workspacesdkagentconnectioninfo) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get running containers for workspace agent

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/containers?label=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}/containers`

### Parameters

| Name             | In    | Type              | Required | Description        |
|------------------|-------|-------------------|----------|--------------------|
| `workspaceagent` | path  | string(uuid)      | true     | Workspace agent ID |
| `label`          | query | string(key=value) | true     | Labels             |

### Example responses

> 200 Response

```json
{
  "containers": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "string",
      "image": "string",
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "name": "string",
      "ports": [
        {
          "host_ip": "string",
          "host_port": 0,
          "network": "string",
          "port": 0
        }
      ],
      "running": true,
      "status": "string",
      "volumes": {
        "property1": "string",
        "property2": "string"
      }
    }
  ],
  "devcontainers": [
    {
      "agent": {
        "directory": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string"
      },
      "config_path": "string",
      "container": {
        "created_at": "2019-08-24T14:15:22Z",
        "id": "string",
        "image": "string",
        "labels": {
          "property1": "string",
          "property2": "string"
        },
        "name": "string",
        "ports": [
          {
            "host_ip": "string",
            "host_port": 0,
            "network": "string",
            "port": 0
          }
        ],
        "running": true,
        "status": "string",
        "volumes": {
          "property1": "string",
          "property2": "string"
        }
      },
      "dirty": true,
      "error": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "status": "running",
      "subagent_id": "7b85d465-b649-4b8b-9da8-5f731c1d294d",
      "workspace_folder": "string"
    }
  ],
  "warnings": [
    "string"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceAgentListContainersResponse](schemas.md#codersdkworkspaceagentlistcontainersresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete devcontainer for workspace agent

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/containers/devcontainers/{devcontainer} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/workspaceagents/{workspaceagent}/containers/devcontainers/{devcontainer}`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspaceagent` | path | string(uuid) | true     | Workspace agent ID |
| `devcontainer`   | path | string       | true     | Devcontainer ID    |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Recreate devcontainer for workspace agent

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/containers/devcontainers/{devcontainer}/recreate \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaceagents/{workspaceagent}/containers/devcontainers/{devcontainer}/recreate`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspaceagent` | path | string(uuid) | true     | Workspace agent ID |
| `devcontainer`   | path | string       | true     | Devcontainer ID    |

### Example responses

> 202 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                       | Description | Schema                                           |
|--------|---------------------------------------------------------------|-------------|--------------------------------------------------|
| 202    | [Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3) | Accepted    | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Watch workspace agent for container updates

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/containers/watch \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}/containers/watch`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspaceagent` | path | string(uuid) | true     | Workspace agent ID |

### Example responses

> 200 Response

```json
{
  "containers": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "string",
      "image": "string",
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "name": "string",
      "ports": [
        {
          "host_ip": "string",
          "host_port": 0,
          "network": "string",
          "port": 0
        }
      ],
      "running": true,
      "status": "string",
      "volumes": {
        "property1": "string",
        "property2": "string"
      }
    }
  ],
  "devcontainers": [
    {
      "agent": {
        "directory": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string"
      },
      "config_path": "string",
      "container": {
        "created_at": "2019-08-24T14:15:22Z",
        "id": "string",
        "image": "string",
        "labels": {
          "property1": "string",
          "property2": "string"
        },
        "name": "string",
        "ports": [
          {
            "host_ip": "string",
            "host_port": 0,
            "network": "string",
            "port": 0
          }
        ],
        "running": true,
        "status": "string",
        "volumes": {
          "property1": "string",
          "property2": "string"
        }
      },
      "dirty": true,
      "error": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "status": "running",
      "subagent_id": "7b85d465-b649-4b8b-9da8-5f731c1d294d",
      "workspace_folder": "string"
    }
  ],
  "warnings": [
    "string"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceAgentListContainersResponse](schemas.md#codersdkworkspaceagentlistcontainersresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Coordinate workspace agent

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/coordinate \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}/coordinate`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspaceagent` | path | string(uuid) | true     | Workspace agent ID |

### Responses

| Status | Meaning                                                                  | Description         | Schema |
|--------|--------------------------------------------------------------------------|---------------------|--------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get listening ports for workspace agent

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/listening-ports \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}/listening-ports`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspaceagent` | path | string(uuid) | true     | Workspace agent ID |

### Example responses

> 200 Response

```json
{
  "ports": [
    {
      "network": "string",
      "port": 0,
      "process_name": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceAgentListeningPortsResponse](schemas.md#codersdkworkspaceagentlisteningportsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get logs by workspace agent

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/logs \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}/logs`

### Parameters

| Name             | In    | Type         | Required | Description                                                                                                                                 |
|------------------|-------|--------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `workspaceagent` | path  | string(uuid) | true     | Workspace agent ID                                                                                                                          |
| `before`         | query | integer      | false    | Before log id                                                                                                                               |
| `after`          | query | integer      | false    | After log id                                                                                                                                |
| `follow`         | query | boolean      | false    | Follow log stream                                                                                                                           |
| `no_compression` | query | boolean      | false    | Disable compression for WebSocket connection                                                                                                |
| `format`         | query | string       | false    | Log output format. Accepted: 'json' (default), 'text' (plain text with RFC3339 timestamps and ANSI colors). Not supported with follow=true. |

#### Enumerated Values

| Parameter | Value(s)       |
|-----------|----------------|
| `format`  | `json`, `text` |

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "id": 0,
    "level": "trace",
    "output": "string",
    "source_id": "ae50a35c-df42-4eff-ba26-f8bc28d2af81"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.WorkspaceAgentLog](schemas.md#codersdkworkspaceagentlog) |

<h3 id="get-logs-by-workspace-agent-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type                                             | Required | Restrictions | Description |
|----------------|--------------------------------------------------|----------|--------------|-------------|
| `[array item]` | array                                            | false    |              |             |
| `» created_at` | string(date-time)                                | false    |              |             |
| `» id`         | integer                                          | false    |              |             |
| `» level`      | [codersdk.LogLevel](schemas.md#codersdkloglevel) | false    |              |             |
| `» output`     | string                                           | false    |              |             |
| `» source_id`  | string(uuid)                                     | false    |              |             |

#### Enumerated Values

| Property | Value(s)                                  |
|----------|-------------------------------------------|
| `level`  | `debug`, `error`, `info`, `trace`, `warn` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Open PTY to workspace agent

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/pty \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}/pty`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspaceagent` | path | string(uuid) | true     | Workspace agent ID |

### Responses

| Status | Meaning                                                                  | Description         | Schema |
|--------|--------------------------------------------------------------------------|---------------------|--------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Removed: Get logs by workspace agent

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceagents/{workspaceagent}/startup-logs \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceagents/{workspaceagent}/startup-logs`

### Parameters

| Name             | In    | Type         | Required | Description                                  |
|------------------|-------|--------------|----------|----------------------------------------------|
| `workspaceagent` | path  | string(uuid) | true     | Workspace agent ID                           |
| `before`         | query | integer      | false    | Before log id                                |
| `after`          | query | integer      | false    | After log id                                 |
| `follow`         | query | boolean      | false    | Follow log stream                            |
| `no_compression` | query | boolean      | false    | Disable compression for WebSocket connection |

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "id": 0,
    "level": "trace",
    "output": "string",
    "source_id": "ae50a35c-df42-4eff-ba26-f8bc28d2af81"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.WorkspaceAgentLog](schemas.md#codersdkworkspaceagentlog) |

<h3 id="removed:-get-logs-by-workspace-agent-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type                                             | Required | Restrictions | Description |
|----------------|--------------------------------------------------|----------|--------------|-------------|
| `[array item]` | array                                            | false    |              |             |
| `» created_at` | string(date-time)                                | false    |              |             |
| `» id`         | integer                                          | false    |              |             |
| `» level`      | [codersdk.LogLevel](schemas.md#codersdkloglevel) | false    |              |             |
| `» output`     | string                                           | false    |              |             |
| `» source_id`  | string(uuid)                                     | false    |              |             |

#### Enumerated Values

| Property | Value(s)                                  |
|----------|-------------------------------------------|
| `level`  | `debug`, `error`, `info`, `trace`, `warn` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Applications

Source: https://coder.com/docs/reference/api/applications

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Redirect to URI with encrypted API key

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/applications/auth-redirect \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/applications/auth-redirect`

### Parameters

| Name           | In    | Type   | Required | Description          |
|----------------|-------|--------|----------|----------------------|
| `redirect_uri` | query | string | false    | Redirect destination |

### Responses

| Status | Meaning                                                                 | Description        | Schema |
|--------|-------------------------------------------------------------------------|--------------------|--------|
| 307    | [Temporary Redirect](https://tools.ietf.org/html/rfc7231#section-6.4.7) | Temporary Redirect |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get applications host

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/applications/host \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/applications/host`

### Example responses

> 200 Response

```json
{
  "host": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                         |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AppHostResponse](schemas.md#codersdkapphostresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Audit

Source: https://coder.com/docs/reference/api/audit

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get audit logs

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/audit?limit=0 \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/audit`

### Parameters

| Name     | In    | Type    | Required | Description  |
|----------|-------|---------|----------|--------------|
| `q`      | query | string  | false    | Search query |
| `limit`  | query | integer | true     | Page limit   |
| `offset` | query | integer | false    | Page offset  |

### Example responses

> 200 Response

```json
{
  "audit_logs": [
    {
      "action": "create",
      "additional_fields": {},
      "description": "string",
      "diff": {
        "property1": {
          "new": null,
          "old": null,
          "secret": true
        },
        "property2": {
          "new": null,
          "old": null,
          "secret": true
        }
      },
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "ip": "string",
      "is_deleted": true,
      "organization": {
        "display_name": "string",
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "request_id": "266ea41d-adf5-480b-af50-15b940c2b846",
      "resource_icon": "string",
      "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
      "resource_link": "string",
      "resource_target": "string",
      "resource_type": "template",
      "status_code": 0,
      "time": "2019-08-24T14:15:22Z",
      "user": {
        "avatar_url": "http://example.com",
        "created_at": "2019-08-24T14:15:22Z",
        "email": "user@example.com",
        "has_ai_seat": true,
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "is_service_account": true,
        "last_seen_at": "2019-08-24T14:15:22Z",
        "login_type": "",
        "name": "string",
        "organization_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "roles": [
          {
            "display_name": "string",
            "name": "string",
            "organization_id": "string"
          }
        ],
        "status": "active",
        "theme_preference": "string",
        "updated_at": "2019-08-24T14:15:22Z",
        "username": "string"
      },
      "user_agent": "string"
    }
  ],
  "count": 0,
  "count_cap": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AuditLogResponse](schemas.md#codersdkauditlogresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Authentication

Source: https://coder.com/docs/reference/api/authentication

<!-- DO NOT EDIT | GENERATED CONTENT -->

Long-lived tokens can be generated to perform actions on behalf of your user account:

```sh
coder tokens create
```

You can use tokens with the Coder's REST API using the `Coder-Session-Token` HTTP header.

```console
curl 'http://coder-server:8080/api/v2/workspaces' \
  -H 'Coder-Session-Token: *****'
```

---

# Authorization

Source: https://coder.com/docs/reference/api/authorization

<!-- DO NOT EDIT | GENERATED CONTENT -->

## List API key scopes

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/auth/scopes \
  -H 'Accept: application/json'
```

`GET /api/v2/auth/scopes`

### Example responses

> 200 Response

```json
{
  "external": [
    "all"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ExternalAPIKeyScopes](schemas.md#codersdkexternalapikeyscopes) |

## Check authorization

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/authcheck \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/authcheck`

> Body parameter

```json
{
  "checks": {
    "property1": {
      "action": "create",
      "object": {
        "any_org": true,
        "organization_id": "string",
        "owner_id": "string",
        "resource_id": "string",
        "resource_type": "*"
      }
    },
    "property2": {
      "action": "create",
      "object": {
        "any_org": true,
        "organization_id": "string",
        "owner_id": "string",
        "resource_id": "string",
        "resource_type": "*"
      }
    }
  }
}
```

### Parameters

| Name   | In   | Type                                                                     | Required | Description           |
|--------|------|--------------------------------------------------------------------------|----------|-----------------------|
| `body` | body | [codersdk.AuthorizationRequest](schemas.md#codersdkauthorizationrequest) | true     | Authorization request |

### Example responses

> 200 Response

```json
{
  "property1": true,
  "property2": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                     |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AuthorizationResponse](schemas.md#codersdkauthorizationresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Log in user

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/login \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'
```

`POST /api/v2/users/login`

> Body parameter

```json
{
  "email": "user@example.com",
  "password": "string"
}
```

### Parameters

| Name   | In   | Type                                                                             | Required | Description   |
|--------|------|----------------------------------------------------------------------------------|----------|---------------|
| `body` | body | [codersdk.LoginWithPasswordRequest](schemas.md#codersdkloginwithpasswordrequest) | true     | Login request |

### Example responses

> 201 Response

```json
{
  "session_token": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                                             |
|--------|--------------------------------------------------------------|-------------|------------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.LoginWithPasswordResponse](schemas.md#codersdkloginwithpasswordresponse) |

## Change password with a one-time passcode

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/otp/change-password \
  -H 'Content-Type: application/json'
```

`POST /api/v2/users/otp/change-password`

> Body parameter

```json
{
  "email": "user@example.com",
  "one_time_passcode": "string",
  "password": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                                             | Required | Description             |
|--------|------|------------------------------------------------------------------------------------------------------------------|----------|-------------------------|
| `body` | body | [codersdk.ChangePasswordWithOneTimePasscodeRequest](schemas.md#codersdkchangepasswordwithonetimepasscoderequest) | true     | Change password request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

## Request one-time passcode

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/otp/request \
  -H 'Content-Type: application/json'
```

`POST /api/v2/users/otp/request`

> Body parameter

```json
{
  "email": "user@example.com"
}
```

### Parameters

| Name   | In   | Type                                                                                       | Required | Description               |
|--------|------|--------------------------------------------------------------------------------------------|----------|---------------------------|
| `body` | body | [codersdk.RequestOneTimePasscodeRequest](schemas.md#codersdkrequestonetimepasscoderequest) | true     | One-time passcode request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

## Validate user password

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/validate-password \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/validate-password`

> Body parameter

```json
{
  "password": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                   | Required | Description                    |
|--------|------|----------------------------------------------------------------------------------------|----------|--------------------------------|
| `body` | body | [codersdk.ValidateUserPasswordRequest](schemas.md#codersdkvalidateuserpasswordrequest) | true     | Validate user password request |

### Example responses

> 200 Response

```json
{
  "details": "string",
  "valid": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ValidateUserPasswordResponse](schemas.md#codersdkvalidateuserpasswordresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Convert user from password to oauth authentication

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/{user}/convert-login \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/{user}/convert-login`

> Body parameter

```json
{
  "password": "string",
  "to_type": ""
}
```

### Parameters

| Name   | In   | Type                                                                   | Required | Description          |
|--------|------|------------------------------------------------------------------------|----------|----------------------|
| `user` | path | string                                                                 | true     | User ID, name, or me |
| `body` | body | [codersdk.ConvertLoginRequest](schemas.md#codersdkconvertloginrequest) | true     | Convert request      |

### Example responses

> 201 Response

```json
{
  "expires_at": "2019-08-24T14:15:22Z",
  "state_string": "string",
  "to_type": "",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                                         |
|--------|--------------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.OAuthConversionResponse](schemas.md#codersdkoauthconversionresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Builds

Source: https://coder.com/docs/reference/api/builds

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get workspace build by user, workspace name, and build number

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacename}/builds/{buildnumber} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/workspace/{workspacename}/builds/{buildnumber}`

### Parameters

| Name            | In   | Type           | Required | Description          |
|-----------------|------|----------------|----------|----------------------|
| `user`          | path | string         | true     | User ID, name, or me |
| `workspacename` | path | string         | true     | Workspace name       |
| `buildnumber`   | path | string(number) | true     | Build number         |

### Example responses

> 200 Response

```json
{
  "build_number": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "daily_cost": 0,
  "deadline": "2019-08-24T14:15:22Z",
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "initiator_name": "string",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "max_deadline": "2019-08-24T14:15:22Z",
  "reason": "initiator",
  "resources": [
    {
      "agents": [
        {
          "api_version": "string",
          "apps": [
            {
              "command": "string",
              "display_name": "string",
              "external": true,
              "group": "string",
              "health": "disabled",
              "healthcheck": {
                "interval": 0,
                "threshold": 0,
                "url": "string"
              },
              "hidden": true,
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "open_in": "slim-window",
              "sharing_level": "owner",
              "slug": "string",
              "statuses": [
                {
                  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                  "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                  "created_at": "2019-08-24T14:15:22Z",
                  "icon": "string",
                  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                  "message": "string",
                  "needs_user_attention": true,
                  "state": "working",
                  "uri": "string",
                  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                }
              ],
              "subdomain": true,
              "subdomain_name": "string",
              "tooltip": "string",
              "url": "string"
            }
          ],
          "architecture": "string",
          "connection_timeout_seconds": 0,
          "created_at": "2019-08-24T14:15:22Z",
          "directory": "string",
          "disconnected_at": "2019-08-24T14:15:22Z",
          "display_apps": [
            "vscode"
          ],
          "environment_variables": {
            "property1": "string",
            "property2": "string"
          },
          "expanded_directory": "string",
          "first_connected_at": "2019-08-24T14:15:22Z",
          "health": {
            "healthy": false,
            "reason": "agent has lost connection"
          },
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "instance_id": "string",
          "last_connected_at": "2019-08-24T14:15:22Z",
          "latency": {
            "property1": {
              "latency_ms": 0,
              "preferred": true
            },
            "property2": {
              "latency_ms": 0,
              "preferred": true
            }
          },
          "lifecycle_state": "created",
          "log_sources": [
            {
              "created_at": "2019-08-24T14:15:22Z",
              "display_name": "string",
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
            }
          ],
          "logs_length": 0,
          "logs_overflowed": true,
          "metadata": [
            {
              "description": {
                "display_name": "string",
                "interval": 0,
                "key": "string",
                "script": "string",
                "timeout": 0
              },
              "result": {
                "age": 0,
                "collected_at": "2019-08-24T14:15:22Z",
                "error": "string",
                "value": "string"
              }
            }
          ],
          "name": "string",
          "operating_system": "string",
          "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
          "ready_at": "2019-08-24T14:15:22Z",
          "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
          "scripts": [
            {
              "cron": "string",
              "display_name": "string",
              "exit_code": 0,
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "log_path": "string",
              "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
              "run_on_start": true,
              "run_on_stop": true,
              "script": "string",
              "start_blocks_login": true,
              "status": "ok",
              "timeout": 0
            }
          ],
          "started_at": "2019-08-24T14:15:22Z",
          "startup_script_behavior": "blocking",
          "status": "connecting",
          "subsystems": [
            "envbox"
          ],
          "troubleshooting_url": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "version": "string"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "daily_cost": 0,
      "hide": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
      "metadata": [
        {
          "key": "string",
          "sensitive": true,
          "value": "string"
        }
      ],
      "name": "string",
      "type": "string",
      "workspace_transition": "start"
    }
  ],
  "status": "pending",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_name": "string",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "transition": "start",
  "updated_at": "2019-08-24T14:15:22Z",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
  "workspace_name": "string",
  "workspace_owner_avatar_url": "string",
  "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
  "workspace_owner_name": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceBuild](schemas.md#codersdkworkspacebuild) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace build

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspacebuilds/{workspacebuild}`

### Parameters

| Name             | In   | Type   | Required | Description        |
|------------------|------|--------|----------|--------------------|
| `workspacebuild` | path | string | true     | Workspace build ID |

### Example responses

> 200 Response

```json
{
  "build_number": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "daily_cost": 0,
  "deadline": "2019-08-24T14:15:22Z",
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "initiator_name": "string",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "max_deadline": "2019-08-24T14:15:22Z",
  "reason": "initiator",
  "resources": [
    {
      "agents": [
        {
          "api_version": "string",
          "apps": [
            {
              "command": "string",
              "display_name": "string",
              "external": true,
              "group": "string",
              "health": "disabled",
              "healthcheck": {
                "interval": 0,
                "threshold": 0,
                "url": "string"
              },
              "hidden": true,
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "open_in": "slim-window",
              "sharing_level": "owner",
              "slug": "string",
              "statuses": [
                {
                  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                  "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                  "created_at": "2019-08-24T14:15:22Z",
                  "icon": "string",
                  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                  "message": "string",
                  "needs_user_attention": true,
                  "state": "working",
                  "uri": "string",
                  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                }
              ],
              "subdomain": true,
              "subdomain_name": "string",
              "tooltip": "string",
              "url": "string"
            }
          ],
          "architecture": "string",
          "connection_timeout_seconds": 0,
          "created_at": "2019-08-24T14:15:22Z",
          "directory": "string",
          "disconnected_at": "2019-08-24T14:15:22Z",
          "display_apps": [
            "vscode"
          ],
          "environment_variables": {
            "property1": "string",
            "property2": "string"
          },
          "expanded_directory": "string",
          "first_connected_at": "2019-08-24T14:15:22Z",
          "health": {
            "healthy": false,
            "reason": "agent has lost connection"
          },
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "instance_id": "string",
          "last_connected_at": "2019-08-24T14:15:22Z",
          "latency": {
            "property1": {
              "latency_ms": 0,
              "preferred": true
            },
            "property2": {
              "latency_ms": 0,
              "preferred": true
            }
          },
          "lifecycle_state": "created",
          "log_sources": [
            {
              "created_at": "2019-08-24T14:15:22Z",
              "display_name": "string",
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
            }
          ],
          "logs_length": 0,
          "logs_overflowed": true,
          "metadata": [
            {
              "description": {
                "display_name": "string",
                "interval": 0,
                "key": "string",
                "script": "string",
                "timeout": 0
              },
              "result": {
                "age": 0,
                "collected_at": "2019-08-24T14:15:22Z",
                "error": "string",
                "value": "string"
              }
            }
          ],
          "name": "string",
          "operating_system": "string",
          "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
          "ready_at": "2019-08-24T14:15:22Z",
          "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
          "scripts": [
            {
              "cron": "string",
              "display_name": "string",
              "exit_code": 0,
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "log_path": "string",
              "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
              "run_on_start": true,
              "run_on_stop": true,
              "script": "string",
              "start_blocks_login": true,
              "status": "ok",
              "timeout": 0
            }
          ],
          "started_at": "2019-08-24T14:15:22Z",
          "startup_script_behavior": "blocking",
          "status": "connecting",
          "subsystems": [
            "envbox"
          ],
          "troubleshooting_url": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "version": "string"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "daily_cost": 0,
      "hide": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
      "metadata": [
        {
          "key": "string",
          "sensitive": true,
          "value": "string"
        }
      ],
      "name": "string",
      "type": "string",
      "workspace_transition": "start"
    }
  ],
  "status": "pending",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_name": "string",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "transition": "start",
  "updated_at": "2019-08-24T14:15:22Z",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
  "workspace_name": "string",
  "workspace_owner_avatar_url": "string",
  "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
  "workspace_owner_name": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceBuild](schemas.md#codersdkworkspacebuild) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Cancel workspace build

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/cancel \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/workspacebuilds/{workspacebuild}/cancel`

### Parameters

| Name             | In    | Type   | Required | Description                                                                                                                                                                              |
|------------------|-------|--------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `workspacebuild` | path  | string | true     | Workspace build ID                                                                                                                                                                       |
| `expect_status`  | query | string | false    | Expected status of the job. If expect_status is supplied, the request will be rejected with 412 Precondition Failed if the job doesn't match the state when performing the cancellation. |

#### Enumerated Values

| Parameter       | Value(s)             |
|-----------------|----------------------|
| `expect_status` | `pending`, `running` |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace build logs

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/logs \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspacebuilds/{workspacebuild}/logs`

### Parameters

| Name             | In    | Type    | Required | Description                                                                                                                                 |
|------------------|-------|---------|----------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `workspacebuild` | path  | string  | true     | Workspace build ID                                                                                                                          |
| `before`         | query | integer | false    | Before log id                                                                                                                               |
| `after`          | query | integer | false    | After log id                                                                                                                                |
| `follow`         | query | boolean | false    | Follow log stream                                                                                                                           |
| `format`         | query | string  | false    | Log output format. Accepted: 'json' (default), 'text' (plain text with RFC3339 timestamps and ANSI colors). Not supported with follow=true. |

#### Enumerated Values

| Parameter | Value(s)       |
|-----------|----------------|
| `format`  | `json`, `text` |

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "id": 0,
    "log_level": "trace",
    "log_source": "provisioner_daemon",
    "output": "string",
    "stage": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ProvisionerJobLog](schemas.md#codersdkprovisionerjoblog) |

<h3 id="get-workspace-build-logs-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type                                               | Required | Restrictions | Description |
|----------------|----------------------------------------------------|----------|--------------|-------------|
| `[array item]` | array                                              | false    |              |             |
| `» created_at` | string(date-time)                                  | false    |              |             |
| `» id`         | integer                                            | false    |              |             |
| `» log_level`  | [codersdk.LogLevel](schemas.md#codersdkloglevel)   | false    |              |             |
| `» log_source` | [codersdk.LogSource](schemas.md#codersdklogsource) | false    |              |             |
| `» output`     | string                                             | false    |              |             |
| `» stage`      | string                                             | false    |              |             |

#### Enumerated Values

| Property     | Value(s)                                  |
|--------------|-------------------------------------------|
| `log_level`  | `debug`, `error`, `info`, `trace`, `warn` |
| `log_source` | `provisioner`, `provisioner_daemon`       |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get build parameters for workspace build

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/parameters \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspacebuilds/{workspacebuild}/parameters`

### Parameters

| Name             | In   | Type   | Required | Description        |
|------------------|------|--------|----------|--------------------|
| `workspacebuild` | path | string | true     | Workspace build ID |

### Example responses

> 200 Response

```json
[
  {
    "name": "string",
    "value": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                  |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.WorkspaceBuildParameter](schemas.md#codersdkworkspacebuildparameter) |

<h3 id="get-build-parameters-for-workspace-build-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `[array item]` | array  | false    |              |             |
| `» name`       | string | false    |              |             |
| `» value`      | string | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Removed: Get workspace resources for workspace build

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/resources \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspacebuilds/{workspacebuild}/resources`

### Parameters

| Name             | In   | Type   | Required | Description        |
|------------------|------|--------|----------|--------------------|
| `workspacebuild` | path | string | true     | Workspace build ID |

### Example responses

> 200 Response

```json
[
  {
    "agents": [
      {
        "api_version": "string",
        "apps": [
          {
            "command": "string",
            "display_name": "string",
            "external": true,
            "group": "string",
            "health": "disabled",
            "healthcheck": {
              "interval": 0,
              "threshold": 0,
              "url": "string"
            },
            "hidden": true,
            "icon": "string",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "open_in": "slim-window",
            "sharing_level": "owner",
            "slug": "string",
            "statuses": [
              {
                "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                "created_at": "2019-08-24T14:15:22Z",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "message": "string",
                "needs_user_attention": true,
                "state": "working",
                "uri": "string",
                "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
              }
            ],
            "subdomain": true,
            "subdomain_name": "string",
            "tooltip": "string",
            "url": "string"
          }
        ],
        "architecture": "string",
        "connection_timeout_seconds": 0,
        "created_at": "2019-08-24T14:15:22Z",
        "directory": "string",
        "disconnected_at": "2019-08-24T14:15:22Z",
        "display_apps": [
          "vscode"
        ],
        "environment_variables": {
          "property1": "string",
          "property2": "string"
        },
        "expanded_directory": "string",
        "first_connected_at": "2019-08-24T14:15:22Z",
        "health": {
          "healthy": false,
          "reason": "agent has lost connection"
        },
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "instance_id": "string",
        "last_connected_at": "2019-08-24T14:15:22Z",
        "latency": {
          "property1": {
            "latency_ms": 0,
            "preferred": true
          },
          "property2": {
            "latency_ms": 0,
            "preferred": true
          }
        },
        "lifecycle_state": "created",
        "log_sources": [
          {
            "created_at": "2019-08-24T14:15:22Z",
            "display_name": "string",
            "icon": "string",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
          }
        ],
        "logs_length": 0,
        "logs_overflowed": true,
        "metadata": [
          {
            "description": {
              "display_name": "string",
              "interval": 0,
              "key": "string",
              "script": "string",
              "timeout": 0
            },
            "result": {
              "age": 0,
              "collected_at": "2019-08-24T14:15:22Z",
              "error": "string",
              "value": "string"
            }
          }
        ],
        "name": "string",
        "operating_system": "string",
        "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
        "ready_at": "2019-08-24T14:15:22Z",
        "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
        "scripts": [
          {
            "cron": "string",
            "display_name": "string",
            "exit_code": 0,
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "log_path": "string",
            "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
            "run_on_start": true,
            "run_on_stop": true,
            "script": "string",
            "start_blocks_login": true,
            "status": "ok",
            "timeout": 0
          }
        ],
        "started_at": "2019-08-24T14:15:22Z",
        "startup_script_behavior": "blocking",
        "status": "connecting",
        "subsystems": [
          "envbox"
        ],
        "troubleshooting_url": "string",
        "updated_at": "2019-08-24T14:15:22Z",
        "version": "string"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "hide": true,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
    "metadata": [
      {
        "key": "string",
        "sensitive": true,
        "value": "string"
      }
    ],
    "name": "string",
    "type": "string",
    "workspace_transition": "start"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.WorkspaceResource](schemas.md#codersdkworkspaceresource) |

<h3 id="removed:-get-workspace-resources-for-workspace-build-responseschema">Response Schema</h3>

Status Code **200**

| Name                            | Type                                                                                                   | Required | Restrictions | Description                                                                                                                                                                                                                                                            |
|---------------------------------|--------------------------------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                  | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `» agents`                      | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» api_version`                | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» apps`                       | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» command`                   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              | Display name is a friendly name for the app.                                                                                                                                                                                                                           |
| `»»» external`                  | boolean                                                                                                | false    |              | External specifies whether the URL should be opened externally on the client or not.                                                                                                                                                                                   |
| `»»» group`                     | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» health`                    | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» healthcheck`               | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck)                                                 | false    |              | Healthcheck specifies the configuration for checking app health.                                                                                                                                                                                                       |
| `»»»» interval`                 | integer                                                                                                | false    |              | Interval specifies the seconds between each health check.                                                                                                                                                                                                              |
| `»»»» threshold`                | integer                                                                                                | false    |              | Threshold specifies the number of consecutive failed health checks before returning "unhealthy".                                                                                                                                                                       |
| `»»»» url`                      | string                                                                                                 | false    |              | URL specifies the endpoint to check for the app health.                                                                                                                                                                                                                |
| `»»» hidden`                    | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» icon`                      | string                                                                                                 | false    |              | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard.                                                                                                                                                                       |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» open_in`                   | [codersdk.WorkspaceAppOpenIn](schemas.md#codersdkworkspaceappopenin)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» sharing_level`             | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel)                       | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» slug`                      | string                                                                                                 | false    |              | Slug is a unique identifier within the agent.                                                                                                                                                                                                                          |
| `»»» statuses`                  | array                                                                                                  | false    |              | Statuses is a list of statuses for the app.                                                                                                                                                                                                                            |
| `»»»» agent_id`                 | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» app_id`                   | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» created_at`               | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» icon`                     | string                                                                                                 | false    |              | Deprecated: This field is unused and will be removed in a future version. Icon is an external URL to an icon that will be rendered in the UI.                                                                                                                          |
| `»»»» id`                       | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» message`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» needs_user_attention`     | boolean                                                                                                | false    |              | Deprecated: This field is unused and will be removed in a future version. NeedsUserAttention specifies whether the status needs user attention.                                                                                                                        |
| `»»»» state`                    | [codersdk.WorkspaceAppStatusState](schemas.md#codersdkworkspaceappstatusstate)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» uri`                      | string                                                                                                 | false    |              | Uri is the URI of the resource that the status is for. e.g. https://github.com/org/repo/pull/123 e.g. file:///path/to/file                                                                                                                                             |
| `»»»» workspace_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» subdomain`                 | boolean                                                                                                | false    |              | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI.                         |
| `»»» subdomain_name`            | string                                                                                                 | false    |              | Subdomain name is the application domain exposed on the `coder server`.                                                                                                                                                                                                |
| `»»» tooltip`                   | string                                                                                                 | false    |              | Tooltip is an optional markdown supported field that is displayed when hovering over workspace apps in the UI.                                                                                                                                                         |
| `»»» url`                       | string                                                                                                 | false    |              | URL is the address being proxied to inside the workspace. If external is specified, this will be opened on the client.                                                                                                                                                 |
| `»» architecture`               | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» connection_timeout_seconds` | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» created_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» directory`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» disconnected_at`            | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» display_apps`               | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» environment_variables`      | object                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» [any property]`            | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» expanded_directory`         | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» first_connected_at`         | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» health`                     | [codersdk.WorkspaceAgentHealth](schemas.md#codersdkworkspaceagenthealth)                               | false    |              | Health reports the health of the agent.                                                                                                                                                                                                                                |
| `»»» healthy`                   | boolean                                                                                                | false    |              | Healthy is true if the agent is healthy.                                                                                                                                                                                                                               |
| `»»» reason`                    | string                                                                                                 | false    |              | Reason is a human-readable explanation of the agent's health. It is empty if Healthy is true.                                                                                                                                                                          |
| `»» id`                         | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» instance_id`                | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» last_connected_at`          | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» latency`                    | object                                                                                                 | false    |              | Latency is mapped by region name (e.g. "New York City", "Seattle").                                                                                                                                                                                                    |
| `»»» [any property]`            | [codersdk.DERPRegion](schemas.md#codersdkderpregion)                                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» latency_ms`               | number                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» preferred`                | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» lifecycle_state`            | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `»» log_sources`                | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» created_at`                | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» icon`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» workspace_agent_id`        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» logs_length`                | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» logs_overflowed`            | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» metadata`                   | array                                                                                                  | false    |              | Metadata is only populated on the workspaces list endpoint when the request opts in with the include_agent_metadata search key, and it only carries the requested keys. The description's script is always empty here: it can be long, and list consumers want values. |
| `»»» description`               | [codersdk.WorkspaceAgentMetadataDescription](schemas.md#codersdkworkspaceagentmetadatadescription)     | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» display_name`             | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» interval`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» key`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» script`                   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» timeout`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» result`                    | [codersdk.WorkspaceAgentMetadataResult](schemas.md#codersdkworkspaceagentmetadataresult)               | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» age`                      | integer                                                                                                | false    |              | Age is the number of seconds since the metadata was collected. It is provided in addition to CollectedAt to protect against clock skew.                                                                                                                                |
| `»»»» collected_at`             | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» error`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» value`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» name`                       | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» operating_system`           | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» parent_id`                  | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» ready_at`                   | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» resource_id`                | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» scripts`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» cron`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» exit_code`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» log_path`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» log_source_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» run_on_start`              | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» run_on_stop`               | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» script`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» start_blocks_login`        | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» status`                    | [codersdk.WorkspaceAgentScriptStatus](schemas.md#codersdkworkspaceagentscriptstatus)                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» timeout`                   | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» started_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» startup_script_behavior`    | [codersdk.WorkspaceAgentStartupScriptBehavior](schemas.md#codersdkworkspaceagentstartupscriptbehavior) | false    |              | Startup script behavior is a legacy field that is deprecated in favor of the `coder_script` resource. It's only referenced by old clients. Deprecated: Remove in the future!                                                                                           |
| `»» status`                     | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus)                               | false    |              |                                                                                                                                                                                                                                                                        |
| `»» subsystems`                 | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» troubleshooting_url`        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» updated_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» version`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» created_at`                  | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `» daily_cost`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» hide`                        | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» icon`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» id`                          | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» job_id`                      | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» metadata`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» key`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» sensitive`                  | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» value`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» name`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» type`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» workspace_transition`        | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)                                 | false    |              |                                                                                                                                                                                                                                                                        |

#### Enumerated Values

| Property                  | Value(s)                                                                                                                     |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------|
| `health`                  | `disabled`, `healthy`, `initializing`, `unhealthy`                                                                           |
| `open_in`                 | `slim-window`, `tab`                                                                                                         |
| `sharing_level`           | `authenticated`, `organization`, `owner`, `public`                                                                           |
| `state`                   | `complete`, `failure`, `idle`, `working`                                                                                     |
| `lifecycle_state`         | `created`, `off`, `ready`, `shutdown_error`, `shutdown_timeout`, `shutting_down`, `start_error`, `start_timeout`, `starting` |
| `status`                  | `connected`, `connecting`, `disconnected`, `exit_failure`, `ok`, `pipes_left_open`, `timed_out`, `timeout`                   |
| `startup_script_behavior` | `blocking`, `non-blocking`                                                                                                   |
| `workspace_transition`    | `delete`, `start`, `stop`                                                                                                    |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get provisioner state for workspace build

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/state \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspacebuilds/{workspacebuild}/state`

### Parameters

| Name             | In   | Type   | Required | Description        |
|------------------|------|--------|----------|--------------------|
| `workspacebuild` | path | string | true     | Workspace build ID |

### Example responses

> 200 Response

```json
{
  "build_number": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "daily_cost": 0,
  "deadline": "2019-08-24T14:15:22Z",
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "initiator_name": "string",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "max_deadline": "2019-08-24T14:15:22Z",
  "reason": "initiator",
  "resources": [
    {
      "agents": [
        {
          "api_version": "string",
          "apps": [
            {
              "command": "string",
              "display_name": "string",
              "external": true,
              "group": "string",
              "health": "disabled",
              "healthcheck": {
                "interval": 0,
                "threshold": 0,
                "url": "string"
              },
              "hidden": true,
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "open_in": "slim-window",
              "sharing_level": "owner",
              "slug": "string",
              "statuses": [
                {
                  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                  "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                  "created_at": "2019-08-24T14:15:22Z",
                  "icon": "string",
                  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                  "message": "string",
                  "needs_user_attention": true,
                  "state": "working",
                  "uri": "string",
                  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                }
              ],
              "subdomain": true,
              "subdomain_name": "string",
              "tooltip": "string",
              "url": "string"
            }
          ],
          "architecture": "string",
          "connection_timeout_seconds": 0,
          "created_at": "2019-08-24T14:15:22Z",
          "directory": "string",
          "disconnected_at": "2019-08-24T14:15:22Z",
          "display_apps": [
            "vscode"
          ],
          "environment_variables": {
            "property1": "string",
            "property2": "string"
          },
          "expanded_directory": "string",
          "first_connected_at": "2019-08-24T14:15:22Z",
          "health": {
            "healthy": false,
            "reason": "agent has lost connection"
          },
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "instance_id": "string",
          "last_connected_at": "2019-08-24T14:15:22Z",
          "latency": {
            "property1": {
              "latency_ms": 0,
              "preferred": true
            },
            "property2": {
              "latency_ms": 0,
              "preferred": true
            }
          },
          "lifecycle_state": "created",
          "log_sources": [
            {
              "created_at": "2019-08-24T14:15:22Z",
              "display_name": "string",
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
            }
          ],
          "logs_length": 0,
          "logs_overflowed": true,
          "metadata": [
            {
              "description": {
                "display_name": "string",
                "interval": 0,
                "key": "string",
                "script": "string",
                "timeout": 0
              },
              "result": {
                "age": 0,
                "collected_at": "2019-08-24T14:15:22Z",
                "error": "string",
                "value": "string"
              }
            }
          ],
          "name": "string",
          "operating_system": "string",
          "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
          "ready_at": "2019-08-24T14:15:22Z",
          "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
          "scripts": [
            {
              "cron": "string",
              "display_name": "string",
              "exit_code": 0,
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "log_path": "string",
              "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
              "run_on_start": true,
              "run_on_stop": true,
              "script": "string",
              "start_blocks_login": true,
              "status": "ok",
              "timeout": 0
            }
          ],
          "started_at": "2019-08-24T14:15:22Z",
          "startup_script_behavior": "blocking",
          "status": "connecting",
          "subsystems": [
            "envbox"
          ],
          "troubleshooting_url": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "version": "string"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "daily_cost": 0,
      "hide": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
      "metadata": [
        {
          "key": "string",
          "sensitive": true,
          "value": "string"
        }
      ],
      "name": "string",
      "type": "string",
      "workspace_transition": "start"
    }
  ],
  "status": "pending",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_name": "string",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "transition": "start",
  "updated_at": "2019-08-24T14:15:22Z",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
  "workspace_name": "string",
  "workspace_owner_avatar_url": "string",
  "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
  "workspace_owner_name": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceBuild](schemas.md#codersdkworkspacebuild) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace build state

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/state \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/workspacebuilds/{workspacebuild}/state`

> Body parameter

```json
{
  "state": [
    0
  ]
}
```

### Parameters

| Name             | In   | Type                                                                                             | Required | Description        |
|------------------|------|--------------------------------------------------------------------------------------------------|----------|--------------------|
| `workspacebuild` | path | string(uuid)                                                                                     | true     | Workspace build ID |
| `body`           | body | [codersdk.UpdateWorkspaceBuildStateRequest](schemas.md#codersdkupdateworkspacebuildstaterequest) | true     | Request body       |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace build timings by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/timings \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspacebuilds/{workspacebuild}/timings`

### Parameters

| Name             | In   | Type         | Required | Description        |
|------------------|------|--------------|----------|--------------------|
| `workspacebuild` | path | string(uuid) | true     | Workspace build ID |

### Example responses

> 200 Response

```json
{
  "agent_connection_timings": [
    {
      "ended_at": "2019-08-24T14:15:22Z",
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z",
      "workspace_agent_id": "string",
      "workspace_agent_name": "string"
    }
  ],
  "agent_script_timings": [
    {
      "display_name": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "exit_code": 0,
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z",
      "status": "string",
      "workspace_agent_id": "string",
      "workspace_agent_name": "string"
    }
  ],
  "provisioner_timings": [
    {
      "action": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
      "resource": "string",
      "source": "string",
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                     |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceBuildTimings](schemas.md#codersdkworkspacebuildtimings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace builds by workspace ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/builds`

### Parameters

| Name        | In    | Type              | Required | Description     |
|-------------|-------|-------------------|----------|-----------------|
| `workspace` | path  | string(uuid)      | true     | Workspace ID    |
| `after_id`  | query | string(uuid)      | false    | After ID        |
| `limit`     | query | integer           | false    | Page limit      |
| `offset`    | query | integer           | false    | Page offset     |
| `since`     | query | string(date-time) | false    | Since timestamp |

### Example responses

> 200 Response

```json
[
  {
    "build_number": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "deadline": "2019-08-24T14:15:22Z",
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "initiator_name": "string",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "max_deadline": "2019-08-24T14:15:22Z",
    "reason": "initiator",
    "resources": [
      {
        "agents": [
          {
            "api_version": "string",
            "apps": [
              {
                "command": "string",
                "display_name": "string",
                "external": true,
                "group": "string",
                "health": "disabled",
                "healthcheck": {
                  "interval": 0,
                  "threshold": 0,
                  "url": "string"
                },
                "hidden": true,
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "open_in": "slim-window",
                "sharing_level": "owner",
                "slug": "string",
                "statuses": [
                  {
                    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                    "created_at": "2019-08-24T14:15:22Z",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "message": "string",
                    "needs_user_attention": true,
                    "state": "working",
                    "uri": "string",
                    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                  }
                ],
                "subdomain": true,
                "subdomain_name": "string",
                "tooltip": "string",
                "url": "string"
              }
            ],
            "architecture": "string",
            "connection_timeout_seconds": 0,
            "created_at": "2019-08-24T14:15:22Z",
            "directory": "string",
            "disconnected_at": "2019-08-24T14:15:22Z",
            "display_apps": [
              "vscode"
            ],
            "environment_variables": {
              "property1": "string",
              "property2": "string"
            },
            "expanded_directory": "string",
            "first_connected_at": "2019-08-24T14:15:22Z",
            "health": {
              "healthy": false,
              "reason": "agent has lost connection"
            },
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "instance_id": "string",
            "last_connected_at": "2019-08-24T14:15:22Z",
            "latency": {
              "property1": {
                "latency_ms": 0,
                "preferred": true
              },
              "property2": {
                "latency_ms": 0,
                "preferred": true
              }
            },
            "lifecycle_state": "created",
            "log_sources": [
              {
                "created_at": "2019-08-24T14:15:22Z",
                "display_name": "string",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
              }
            ],
            "logs_length": 0,
            "logs_overflowed": true,
            "metadata": [
              {
                "description": {
                  "display_name": "string",
                  "interval": 0,
                  "key": "string",
                  "script": "string",
                  "timeout": 0
                },
                "result": {
                  "age": 0,
                  "collected_at": "2019-08-24T14:15:22Z",
                  "error": "string",
                  "value": "string"
                }
              }
            ],
            "name": "string",
            "operating_system": "string",
            "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
            "ready_at": "2019-08-24T14:15:22Z",
            "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
            "scripts": [
              {
                "cron": "string",
                "display_name": "string",
                "exit_code": 0,
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "log_path": "string",
                "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                "run_on_start": true,
                "run_on_stop": true,
                "script": "string",
                "start_blocks_login": true,
                "status": "ok",
                "timeout": 0
              }
            ],
            "started_at": "2019-08-24T14:15:22Z",
            "startup_script_behavior": "blocking",
            "status": "connecting",
            "subsystems": [
              "envbox"
            ],
            "troubleshooting_url": "string",
            "updated_at": "2019-08-24T14:15:22Z",
            "version": "string"
          }
        ],
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "hide": true,
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
        "metadata": [
          {
            "key": "string",
            "sensitive": true,
            "value": "string"
          }
        ],
        "name": "string",
        "type": "string",
        "workspace_transition": "start"
      }
    ],
    "status": "pending",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_name": "string",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start",
    "updated_at": "2019-08-24T14:15:22Z",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string",
    "workspace_owner_avatar_url": "string",
    "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
    "workspace_owner_name": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.WorkspaceBuild](schemas.md#codersdkworkspacebuild) |

<h3 id="get-workspace-builds-by-workspace-id-responseschema">Response Schema</h3>

Status Code **200**

| Name                             | Type                                                                                                   | Required | Restrictions | Description                                                                                                                                                                                                                                                            |
|----------------------------------|--------------------------------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                   | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `» build_number`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» created_at`                   | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `» daily_cost`                   | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» deadline`                     | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `» has_external_agent`           | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» id`                           | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» initiator_id`                 | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» initiator_name`               | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» job`                          | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob)                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» available_workers`           | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» canceled_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» completed_at`                | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» created_at`                  | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» error`                       | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» error_code`                  | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode)                                               | false    |              |                                                                                                                                                                                                                                                                        |
| `»» file_id`                     | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» id`                          | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» initiator_id`                | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» input`                       | [codersdk.ProvisionerJobInput](schemas.md#codersdkprovisionerjobinput)                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» error`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» template_version_id`        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» workspace_build_id`         | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» logs_overflowed`             | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» metadata`                    | [codersdk.ProvisionerJobMetadata](schemas.md#codersdkprovisionerjobmetadata)                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» template_display_name`      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» template_icon`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» template_id`                | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» template_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» template_version_name`      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» workspace_build_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» workspace_id`               | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» workspace_name`             | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» organization_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» queue_position`              | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» queue_size`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» started_at`                  | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» status`                      | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus)                               | false    |              |                                                                                                                                                                                                                                                                        |
| `»» tags`                        | object                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» [any property]`             | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» type`                        | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»» worker_id`                   | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» worker_name`                 | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» matched_provisioners`         | [codersdk.MatchedProvisioners](schemas.md#codersdkmatchedprovisioners)                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» available`                   | integer                                                                                                | false    |              | Available is the number of provisioner daemons that are available to take jobs. This may be less than the count if some provisioners are busy or have been stopped.                                                                                                    |
| `»» count`                       | integer                                                                                                | false    |              | Count is the number of provisioner daemons that matched the given tags. If the count is 0, it means no provisioner daemons matched the requested tags.                                                                                                                 |
| `»» most_recently_seen`          | string(date-time)                                                                                      | false    |              | Most recently seen is the most recently seen time of the set of matched provisioners. If no provisioners matched, this field will be null.                                                                                                                             |
| `» max_deadline`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `» reason`                       | [codersdk.BuildReason](schemas.md#codersdkbuildreason)                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» resources`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» agents`                      | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» api_version`                | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» apps`                       | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» command`                   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» display_name`              | string                                                                                                 | false    |              | Display name is a friendly name for the app.                                                                                                                                                                                                                           |
| `»»»» external`                  | boolean                                                                                                | false    |              | External specifies whether the URL should be opened externally on the client or not.                                                                                                                                                                                   |
| `»»»» group`                     | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» health`                    | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» healthcheck`               | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck)                                                 | false    |              | Healthcheck specifies the configuration for checking app health.                                                                                                                                                                                                       |
| `»»»»» interval`                 | integer                                                                                                | false    |              | Interval specifies the seconds between each health check.                                                                                                                                                                                                              |
| `»»»»» threshold`                | integer                                                                                                | false    |              | Threshold specifies the number of consecutive failed health checks before returning "unhealthy".                                                                                                                                                                       |
| `»»»»» url`                      | string                                                                                                 | false    |              | URL specifies the endpoint to check for the app health.                                                                                                                                                                                                                |
| `»»»» hidden`                    | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» icon`                      | string                                                                                                 | false    |              | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard.                                                                                                                                                                       |
| `»»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» open_in`                   | [codersdk.WorkspaceAppOpenIn](schemas.md#codersdkworkspaceappopenin)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» sharing_level`             | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel)                       | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» slug`                      | string                                                                                                 | false    |              | Slug is a unique identifier within the agent.                                                                                                                                                                                                                          |
| `»»»» statuses`                  | array                                                                                                  | false    |              | Statuses is a list of statuses for the app.                                                                                                                                                                                                                            |
| `»»»»» agent_id`                 | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» app_id`                   | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» created_at`               | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» icon`                     | string                                                                                                 | false    |              | Deprecated: This field is unused and will be removed in a future version. Icon is an external URL to an icon that will be rendered in the UI.                                                                                                                          |
| `»»»»» id`                       | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» message`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» needs_user_attention`     | boolean                                                                                                | false    |              | Deprecated: This field is unused and will be removed in a future version. NeedsUserAttention specifies whether the status needs user attention.                                                                                                                        |
| `»»»»» state`                    | [codersdk.WorkspaceAppStatusState](schemas.md#codersdkworkspaceappstatusstate)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» uri`                      | string                                                                                                 | false    |              | Uri is the URI of the resource that the status is for. e.g. https://github.com/org/repo/pull/123 e.g. file:///path/to/file                                                                                                                                             |
| `»»»»» workspace_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» subdomain`                 | boolean                                                                                                | false    |              | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI.                         |
| `»»»» subdomain_name`            | string                                                                                                 | false    |              | Subdomain name is the application domain exposed on the `coder server`.                                                                                                                                                                                                |
| `»»»» tooltip`                   | string                                                                                                 | false    |              | Tooltip is an optional markdown supported field that is displayed when hovering over workspace apps in the UI.                                                                                                                                                         |
| `»»»» url`                       | string                                                                                                 | false    |              | URL is the address being proxied to inside the workspace. If external is specified, this will be opened on the client.                                                                                                                                                 |
| `»»» architecture`               | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» connection_timeout_seconds` | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» created_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» directory`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» disconnected_at`            | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_apps`               | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» environment_variables`      | object                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» [any property]`            | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» expanded_directory`         | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» first_connected_at`         | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» health`                     | [codersdk.WorkspaceAgentHealth](schemas.md#codersdkworkspaceagenthealth)                               | false    |              | Health reports the health of the agent.                                                                                                                                                                                                                                |
| `»»»» healthy`                   | boolean                                                                                                | false    |              | Healthy is true if the agent is healthy.                                                                                                                                                                                                                               |
| `»»»» reason`                    | string                                                                                                 | false    |              | Reason is a human-readable explanation of the agent's health. It is empty if Healthy is true.                                                                                                                                                                          |
| `»»» id`                         | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» instance_id`                | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» last_connected_at`          | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» latency`                    | object                                                                                                 | false    |              | Latency is mapped by region name (e.g. "New York City", "Seattle").                                                                                                                                                                                                    |
| `»»»» [any property]`            | [codersdk.DERPRegion](schemas.md#codersdkderpregion)                                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» latency_ms`               | number                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» preferred`                | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» lifecycle_state`            | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» log_sources`                | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» created_at`                | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» display_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» icon`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» workspace_agent_id`        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» logs_length`                | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» logs_overflowed`            | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» metadata`                   | array                                                                                                  | false    |              | Metadata is only populated on the workspaces list endpoint when the request opts in with the include_agent_metadata search key, and it only carries the requested keys. The description's script is always empty here: it can be long, and list consumers want values. |
| `»»»» description`               | [codersdk.WorkspaceAgentMetadataDescription](schemas.md#codersdkworkspaceagentmetadatadescription)     | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» display_name`             | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» interval`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» key`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» script`                   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» timeout`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» result`                    | [codersdk.WorkspaceAgentMetadataResult](schemas.md#codersdkworkspaceagentmetadataresult)               | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» age`                      | integer                                                                                                | false    |              | Age is the number of seconds since the metadata was collected. It is provided in addition to CollectedAt to protect against clock skew.                                                                                                                                |
| `»»»»» collected_at`             | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» error`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»»» value`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» name`                       | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» operating_system`           | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» parent_id`                  | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» ready_at`                   | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» resource_id`                | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» scripts`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» cron`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» display_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» exit_code`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» log_path`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» log_source_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» run_on_start`              | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» run_on_stop`               | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» script`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» start_blocks_login`        | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» status`                    | [codersdk.WorkspaceAgentScriptStatus](schemas.md#codersdkworkspaceagentscriptstatus)                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» timeout`                   | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» started_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» startup_script_behavior`    | [codersdk.WorkspaceAgentStartupScriptBehavior](schemas.md#codersdkworkspaceagentstartupscriptbehavior) | false    |              | Startup script behavior is a legacy field that is deprecated in favor of the `coder_script` resource. It's only referenced by old clients. Deprecated: Remove in the future!                                                                                           |
| `»»» status`                     | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus)                               | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» subsystems`                 | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» troubleshooting_url`        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» updated_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» version`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» created_at`                  | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» daily_cost`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» hide`                        | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» icon`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» id`                          | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» job_id`                      | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» metadata`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» key`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» sensitive`                  | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» value`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» name`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» type`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» workspace_transition`        | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» status`                       | [codersdk.WorkspaceStatus](schemas.md#codersdkworkspacestatus)                                         | false    |              |                                                                                                                                                                                                                                                                        |
| `» template_version_id`          | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» template_version_name`        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» template_version_preset_id`   | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» transition`                   | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» updated_at`                   | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `» workspace_id`                 | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» workspace_name`               | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» workspace_owner_avatar_url`   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» workspace_owner_id`           | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» workspace_owner_name`         | string                                                                                                 | false    |              | Workspace owner name is the username of the owner of the workspace.                                                                                                                                                                                                    |

#### Enumerated Values

| Property                     | Value(s)                                                                                                                                                                                                                                   |
|------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `error_code`                 | `INSUFFICIENT_QUOTA`, `REQUIRED_TEMPLATE_VARIABLES`                                                                                                                                                                                        |
| `workspace_build_transition` | `delete`, `start`, `stop`                                                                                                                                                                                                                  |
| `status`                     | `canceled`, `canceling`, `connected`, `connecting`, `deleted`, `deleting`, `disconnected`, `exit_failure`, `failed`, `ok`, `pending`, `pipes_left_open`, `running`, `starting`, `stopped`, `stopping`, `succeeded`, `timed_out`, `timeout` |
| `type`                       | `template_version_dry_run`, `template_version_import`, `workspace_build`                                                                                                                                                                   |
| `reason`                     | `autostart`, `autostop`, `initiator`                                                                                                                                                                                                       |
| `health`                     | `disabled`, `healthy`, `initializing`, `unhealthy`                                                                                                                                                                                         |
| `open_in`                    | `slim-window`, `tab`                                                                                                                                                                                                                       |
| `sharing_level`              | `authenticated`, `organization`, `owner`, `public`                                                                                                                                                                                         |
| `state`                      | `complete`, `failure`, `idle`, `working`                                                                                                                                                                                                   |
| `lifecycle_state`            | `created`, `off`, `ready`, `shutdown_error`, `shutdown_timeout`, `shutting_down`, `start_error`, `start_timeout`, `starting`                                                                                                               |
| `startup_script_behavior`    | `blocking`, `non-blocking`                                                                                                                                                                                                                 |
| `workspace_transition`       | `delete`, `start`, `stop`                                                                                                                                                                                                                  |
| `transition`                 | `delete`, `start`, `stop`                                                                                                                                                                                                                  |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create workspace build

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaces/{workspace}/builds`

> Body parameter

```json
{
  "dry_run": true,
  "log_level": "debug",
  "on_success": {
    "rich_parameter_values": [
      {
        "name": "string",
        "value": "string"
      }
    ],
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start"
  },
  "orphan": true,
  "reason": "dashboard",
  "rich_parameter_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "state": [
    0
  ],
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "transition": "start"
}
```

### Parameters

| Name        | In   | Type                                                                                   | Required | Description                    |
|-------------|------|----------------------------------------------------------------------------------------|----------|--------------------------------|
| `workspace` | path | string(uuid)                                                                           | true     | Workspace ID                   |
| `body`      | body | [codersdk.CreateWorkspaceBuildRequest](schemas.md#codersdkcreateworkspacebuildrequest) | true     | Create workspace build request |

### Example responses

> 201 Response

```json
{
  "build_number": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "daily_cost": 0,
  "deadline": "2019-08-24T14:15:22Z",
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "initiator_name": "string",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "max_deadline": "2019-08-24T14:15:22Z",
  "reason": "initiator",
  "resources": [
    {
      "agents": [
        {
          "api_version": "string",
          "apps": [
            {
              "command": "string",
              "display_name": "string",
              "external": true,
              "group": "string",
              "health": "disabled",
              "healthcheck": {
                "interval": 0,
                "threshold": 0,
                "url": "string"
              },
              "hidden": true,
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "open_in": "slim-window",
              "sharing_level": "owner",
              "slug": "string",
              "statuses": [
                {
                  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                  "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                  "created_at": "2019-08-24T14:15:22Z",
                  "icon": "string",
                  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                  "message": "string",
                  "needs_user_attention": true,
                  "state": "working",
                  "uri": "string",
                  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                }
              ],
              "subdomain": true,
              "subdomain_name": "string",
              "tooltip": "string",
              "url": "string"
            }
          ],
          "architecture": "string",
          "connection_timeout_seconds": 0,
          "created_at": "2019-08-24T14:15:22Z",
          "directory": "string",
          "disconnected_at": "2019-08-24T14:15:22Z",
          "display_apps": [
            "vscode"
          ],
          "environment_variables": {
            "property1": "string",
            "property2": "string"
          },
          "expanded_directory": "string",
          "first_connected_at": "2019-08-24T14:15:22Z",
          "health": {
            "healthy": false,
            "reason": "agent has lost connection"
          },
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "instance_id": "string",
          "last_connected_at": "2019-08-24T14:15:22Z",
          "latency": {
            "property1": {
              "latency_ms": 0,
              "preferred": true
            },
            "property2": {
              "latency_ms": 0,
              "preferred": true
            }
          },
          "lifecycle_state": "created",
          "log_sources": [
            {
              "created_at": "2019-08-24T14:15:22Z",
              "display_name": "string",
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
            }
          ],
          "logs_length": 0,
          "logs_overflowed": true,
          "metadata": [
            {
              "description": {
                "display_name": "string",
                "interval": 0,
                "key": "string",
                "script": "string",
                "timeout": 0
              },
              "result": {
                "age": 0,
                "collected_at": "2019-08-24T14:15:22Z",
                "error": "string",
                "value": "string"
              }
            }
          ],
          "name": "string",
          "operating_system": "string",
          "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
          "ready_at": "2019-08-24T14:15:22Z",
          "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
          "scripts": [
            {
              "cron": "string",
              "display_name": "string",
              "exit_code": 0,
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "log_path": "string",
              "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
              "run_on_start": true,
              "run_on_stop": true,
              "script": "string",
              "start_blocks_login": true,
              "status": "ok",
              "timeout": 0
            }
          ],
          "started_at": "2019-08-24T14:15:22Z",
          "startup_script_behavior": "blocking",
          "status": "connecting",
          "subsystems": [
            "envbox"
          ],
          "troubleshooting_url": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "version": "string"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "daily_cost": 0,
      "hide": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
      "metadata": [
        {
          "key": "string",
          "sensitive": true,
          "value": "string"
        }
      ],
      "name": "string",
      "type": "string",
      "workspace_transition": "start"
    }
  ],
  "status": "pending",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_name": "string",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "transition": "start",
  "updated_at": "2019-08-24T14:15:22Z",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
  "workspace_name": "string",
  "workspace_owner_avatar_url": "string",
  "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
  "workspace_owner_name": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                       |
|--------|--------------------------------------------------------------|-------------|--------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.WorkspaceBuild](schemas.md#codersdkworkspacebuild) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Chats

Source: https://coder.com/docs/reference/api/chats

<!-- DO NOT EDIT | GENERATED CONTENT -->

Programmatic API for Coder Agents (the user-facing "Coder Agents" / "Chats" product). Use these endpoints to create, list, and manage AI coding agent sessions.

## Connect to chat workspace desktop via WebSockets

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/experimental/chats/{chat}/stream/desktop \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/experimental/chats/{chat}/stream/desktop`

Raw binary WebSocket stream of the chat workspace desktop.
Experimental: this endpoint is subject to change.

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Responses

| Status | Meaning                                                                  | Description         | Schema |
|--------|--------------------------------------------------------------------------|---------------------|--------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List chats

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats`

### Parameters

| Name       | In    | Type          | Required | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
|------------|-------|---------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `q`        | query | string        | false    | Search query. Supports `title:<substring>` (case-insensitive, quote multi-word values), `archived:bool`, `has_unread:bool`, `status:<waiting\|running\|error\|requires_action\|interrupting>` (chat status, repeated or comma-separated), `pr_status:<draft\|open\|merged\|closed\|none>` (none matches chats with no pull request) as repeated or comma-separated values, `source:<created_by_me\|shared_with_me>`, `diff_url:<url>` (quote values containing colons), `pr:<number>` (exact PR number match), `repo:<owner/repo>` (case-insensitive substring match against git remote origin or URL), `pr_title:<text>` (case-insensitive PR title substring), `search:<text>` (full-text search across chat titles, PR titles, PR numbers, and message bodies; message bodies match English word stems, e.g. `refactor` matches `refactoring`, and ignore English stopwords; titles and PR titles match whole words case-insensitively without stemming; quote multi-word values; cannot be combined with title, pr_title, or pr; a value that tokenizes to no searchable words, e.g. punctuation only, returns an empty list). Bare terms are not supported; use `title:<value>` or `search:<value>`. |
| `label`    | query | array[string] | false    | Filter by label as key:value. Repeat for multiple (AND logic).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `after_id` | query | string(uuid)  | false    | After ID                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `limit`    | query | integer       | false    | Page limit                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `offset`   | query | integer       | false    | Page offset                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |

### Example responses

> 200 Response

```json
[
  {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "archived": true,
    "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
    "children": [
      {}
    ],
    "client_type": "ui",
    "context": {
      "dirty": true,
      "dirty_since": "2019-08-24T14:15:22Z",
      "error": "string",
      "resources": [
        {
          "error": "string",
          "kind": "instruction_file",
          "size_bytes": 0,
          "skill_description": "string",
          "skill_name": "string",
          "source": "string",
          "status": "ok",
          "tools": [
            {
              "description": "string",
              "name": "string"
            }
          ]
        }
      ]
    },
    "created_at": "2019-08-24T14:15:22Z",
    "diff_status": {
      "additions": 0,
      "approved": true,
      "author_avatar_url": "string",
      "author_login": "string",
      "base_branch": "string",
      "changed_files": 0,
      "changes_requested": true,
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "commits": 0,
      "deletions": 0,
      "head_branch": "string",
      "pr_number": 0,
      "pull_request_draft": true,
      "pull_request_state": "string",
      "pull_request_title": "string",
      "refreshed_at": "2019-08-24T14:15:22Z",
      "reviewer_count": 0,
      "stale_at": "2019-08-24T14:15:22Z",
      "url": "string"
    },
    "files": [
      {
        "created_at": "2019-08-24T14:15:22Z",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "mime_type": "string",
        "name": "string",
        "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
        "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
        "size_bytes": 0
      }
    ],
    "has_unread": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "inline_mcp_servers": [
      {
        "allow_in_subagents": true,
        "created_at": "2019-08-24T14:15:22Z",
        "forward_coder_headers": true,
        "has_custom_headers": true,
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "slug": "string",
        "tool_allow_list": [
          "string"
        ],
        "tool_deny_list": [
          "string"
        ],
        "updated_at": "2019-08-24T14:15:22Z",
        "url": "string"
      }
    ],
    "labels": {
      "property1": "string",
      "property2": "string"
    },
    "last_error": {
      "detail": "string",
      "kind": "generic",
      "message": "string",
      "provider": "string",
      "retryable": true,
      "status_code": 0
    },
    "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
    "last_reasoning_effort": "string",
    "last_turn_summary": "string",
    "mcp_server_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
    "owner_name": "string",
    "owner_username": "string",
    "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
    "pin_order": 0,
    "plan_mode": "plan",
    "queued_for_capacity": true,
    "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
    "shared": true,
    "status": "waiting",
    "summary": "string",
    "title": "string",
    "updated_at": "2019-08-24T14:15:22Z",
    "warnings": [
      "string"
    ],
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                            |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Chat](schemas.md#codersdkchat) |

<h3 id="list-chats-responseschema">Response Schema</h3>

Status Code **200**

| Name                       | Type                                                                               | Required | Restrictions | Description                                                                                                                                                                                                                                                                |
|----------------------------|------------------------------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`             | array                                                                              | false    |              |                                                                                                                                                                                                                                                                            |
| `» agent_id`               | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» archived`               | boolean                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `» build_id`               | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» children`               | [codersdk.Chat](schemas.md#codersdkchat)                                           | false    |              | Children holds child (subagent) chats nested under this root chat. Always initialized to an empty slice so the JSON field is present as []. Child chats cannot create their own subagents, so nesting depth is capped at 1 and this slice is always empty for child chats. |
| `» client_type`            | [codersdk.ChatClientType](schemas.md#codersdkchatclienttype)                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» context`                | [codersdk.ChatContext](schemas.md#codersdkchatcontext)                             | false    |              | Context reports the chat's pinned workspace-context state and whether it has drifted from the agent's latest pushed snapshot. Nil when the chat has no pinned context yet.                                                                                                 |
| `»» dirty`                 | boolean                                                                            | false    |              | Dirty is true when the agent's latest snapshot hash differs from the chat's pinned hash.                                                                                                                                                                                   |
| `»» dirty_since`           | string(date-time)                                                                  | false    |              | Dirty since is when drift was first detected; nil when not dirty.                                                                                                                                                                                                          |
| `»» error`                 | string                                                                             | false    |              | Error is the snapshot-level error copied from the pinned snapshot (empty when healthy).                                                                                                                                                                                    |
| `»» resources`             | array                                                                              | false    |              | Resources is the chat's pinned context (instruction files and skills) the prompt is built from, metadata only (no bodies). It is populated only on the single-chat GET response; list and watch payloads leave it nil to stay lightweight.                                 |
| `»»» error`                | string                                                                             | false    |              | Error explains a non-ok Status; empty when healthy. May also carry a non-fatal warning when Status is ok.                                                                                                                                                                  |
| `»»» kind`                 | [codersdk.ChatContextResourceKind](schemas.md#codersdkchatcontextresourcekind)     | false    |              |                                                                                                                                                                                                                                                                            |
| `»»» size_bytes`           | integer                                                                            | false    |              | Size bytes is the original payload size in bytes.                                                                                                                                                                                                                          |
| `»»» skill_description`    | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»»» skill_name`           | string                                                                             | false    |              | Skill name and SkillDescription are populated only for skill kinds.                                                                                                                                                                                                        |
| `»»» source`               | string                                                                             | false    |              | Source is the resource locator: the canonical file path for an instruction file, the skill directory for a skill, the file path for an MCP config, or the server name for an MCP server.                                                                                   |
| `»»» status`               | [codersdk.ChatContextResourceStatus](schemas.md#codersdkchatcontextresourcestatus) | false    |              | Status is the resource's health. Non-ok resources (invalid, unreadable, oversize, excluded) are still reported so the UI can surface why a resource was dropped from the prompt instead of silently omitting it; their body-specific fields (skill name, tools) are empty. |
| `»»» tools`                | array                                                                              | false    |              | Tools lists the tools exposed by an MCP server. Populated only for the mcp_server kind; nil otherwise.                                                                                                                                                                     |
| `»»»» description`         | string                                                                             | false    |              | Description is the tool's human-readable summary; may be empty.                                                                                                                                                                                                            |
| `»»»» name`                | string                                                                             | false    |              | Name is the tool name with the `<server>__` prefix the agent adds stripped, so it reads as the server exposes it.                                                                                                                                                          |
| `» created_at`             | string(date-time)                                                                  | false    |              |                                                                                                                                                                                                                                                                            |
| `» diff_status`            | [codersdk.ChatDiffStatus](schemas.md#codersdkchatdiffstatus)                       | false    |              |                                                                                                                                                                                                                                                                            |
| `»» additions`             | integer                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» approved`              | boolean                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» author_avatar_url`     | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» author_login`          | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» base_branch`           | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» changed_files`         | integer                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» changes_requested`     | boolean                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» chat_id`               | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `»» commits`               | integer                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» deletions`             | integer                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» head_branch`           | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» pr_number`             | integer                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» pull_request_draft`    | boolean                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» pull_request_state`    | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» pull_request_title`    | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» refreshed_at`          | string(date-time)                                                                  | false    |              |                                                                                                                                                                                                                                                                            |
| `»» reviewer_count`        | integer                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» stale_at`              | string(date-time)                                                                  | false    |              |                                                                                                                                                                                                                                                                            |
| `»» url`                   | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `» files`                  | array                                                                              | false    |              |                                                                                                                                                                                                                                                                            |
| `»» created_at`            | string(date-time)                                                                  | false    |              |                                                                                                                                                                                                                                                                            |
| `»» id`                    | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `»» mime_type`             | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» name`                  | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» organization_id`       | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `»» owner_id`              | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `»» size_bytes`            | integer                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `» has_unread`             | boolean                                                                            | false    |              | Has unread is true when assistant messages exist beyond the owner's read cursor, which updates on stream connect and disconnect and via UpdateChatRequest.Read.                                                                                                            |
| `» id`                     | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» inline_mcp_servers`     | array                                                                              | false    |              | Inline mcp servers lists the inline MCP servers declared on the chat, without headers. Only the single-chat GET sets it. Experimental.                                                                                                                                     |
| `»» allow_in_subagents`    | boolean                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» created_at`            | string(date-time)                                                                  | false    |              |                                                                                                                                                                                                                                                                            |
| `»» forward_coder_headers` | boolean                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» has_custom_headers`    | boolean                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `»» id`                    | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `»» slug`                  | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» tool_allow_list`       | array                                                                              | false    |              |                                                                                                                                                                                                                                                                            |
| `»» tool_deny_list`        | array                                                                              | false    |              |                                                                                                                                                                                                                                                                            |
| `»» updated_at`            | string(date-time)                                                                  | false    |              |                                                                                                                                                                                                                                                                            |
| `»» url`                   | string                                                                             | false    |              | URL is empty unless the chat owner makes the request.                                                                                                                                                                                                                      |
| `» labels`                 | object                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `»» [any property]`        | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `» last_error`             | [codersdk.ChatError](schemas.md#codersdkchaterror)                                 | false    |              |                                                                                                                                                                                                                                                                            |
| `»» detail`                | string                                                                             | false    |              | Detail is optional provider-specific context shown alongside the normalized error message when available.                                                                                                                                                                  |
| `»» kind`                  | [codersdk.ChatErrorKind](schemas.md#codersdkchaterrorkind)                         | false    |              | Kind classifies the error for consistent client rendering.                                                                                                                                                                                                                 |
| `»» message`               | string                                                                             | false    |              | Message is the normalized, user-facing error message.                                                                                                                                                                                                                      |
| `»» provider`              | string                                                                             | false    |              | Provider identifies the upstream model provider when known.                                                                                                                                                                                                                |
| `»» retryable`             | boolean                                                                            | false    |              | Retryable reports whether the underlying error is transient.                                                                                                                                                                                                               |
| `»» status_code`           | integer                                                                            | false    |              | Status code is the best-effort upstream HTTP status code.                                                                                                                                                                                                                  |
| `» last_model_config_id`   | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» last_reasoning_effort`  | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `» last_turn_summary`      | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `» mcp_server_ids`         | array                                                                              | false    |              |                                                                                                                                                                                                                                                                            |
| `» organization_id`        | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» owner_id`               | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» owner_name`             | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `» owner_username`         | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `» parent_chat_id`         | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» pin_order`              | integer                                                                            | false    |              |                                                                                                                                                                                                                                                                            |
| `» plan_mode`              | [codersdk.ChatPlanMode](schemas.md#codersdkchatplanmode)                           | false    |              |                                                                                                                                                                                                                                                                            |
| `» queued_for_capacity`    | boolean                                                                            | false    |              | Queued for capacity reports that the chat is waiting for a concurrent agent slot. Single-chat reads derive it; list responses leave it false.                                                                                                                              |
| `» root_chat_id`           | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |
| `» shared`                 | boolean                                                                            | false    |              | Shared is true when this chat's root chat has explicit user or group ACL entries.                                                                                                                                                                                          |
| `» status`                 | [codersdk.ChatStatus](schemas.md#codersdkchatstatus)                               | false    |              |                                                                                                                                                                                                                                                                            |
| `» summary`                | string                                                                             | false    |              | Summary is the persisted whole-chat summary, generated in the background. It is nil until the first summary has been produced.                                                                                                                                             |
| `» title`                  | string                                                                             | false    |              |                                                                                                                                                                                                                                                                            |
| `» updated_at`             | string(date-time)                                                                  | false    |              |                                                                                                                                                                                                                                                                            |
| `» warnings`               | array                                                                              | false    |              |                                                                                                                                                                                                                                                                            |
| `» workspace_id`           | string(uuid)                                                                       | false    |              |                                                                                                                                                                                                                                                                            |

#### Enumerated Values

| Property      | Value(s)                                                                                                                                                                                                                                                          |
|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `client_type` | `api`, `ui`                                                                                                                                                                                                                                                       |
| `kind`        | `auth`, `config`, `content_filter`, `generic`, `hook_denied`, `hook_dispatch_failed`, `instruction_file`, `mcp_config`, `mcp_server`, `missing_key`, `overloaded`, `provider_disabled`, `rate_limit`, `skill`, `stream_silence_timeout`, `timeout`, `usage_limit` |
| `status`      | `error`, `excluded`, `interrupting`, `invalid`, `ok`, `oversize`, `requires_action`, `running`, `unreadable`, `waiting`                                                                                                                                           |
| `plan_mode`   | `plan`                                                                                                                                                                                                                                                            |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create chat

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/chats`

> Body parameter

```json
{
  "client_type": "ui",
  "content": [
    {
      "content": "string",
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "start_line": 0,
      "text": "string",
      "type": "text",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    }
  ],
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "forward_coder_headers": true,
      "headers": {
        "property1": "string",
        "property2": "string"
      },
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "url": "string"
    }
  ],
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "plan_mode": "plan",
  "reasoning_effort": "string",
  "system_prompt": "string",
  "unsafe_dynamic_tools": [
    {
      "description": "string",
      "input_schema": [
        0
      ],
      "name": "string"
    }
  ],
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Parameters

| Name   | In   | Type                                                               | Required | Description         |
|--------|------|--------------------------------------------------------------------|----------|---------------------|
| `body` | body | [codersdk.CreateChatRequest](schemas.md#codersdkcreatechatrequest) | true     | Create chat request |

### Example responses

> 201 Response

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "archived": true,
  "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
  "children": [
    {
      "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
      "archived": true,
      "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
      "children": [],
      "client_type": "ui",
      "context": {
        "dirty": true,
        "dirty_since": "2019-08-24T14:15:22Z",
        "error": "string",
        "resources": [
          {
            "error": "string",
            "kind": "instruction_file",
            "size_bytes": 0,
            "skill_description": "string",
            "skill_name": "string",
            "source": "string",
            "status": "ok",
            "tools": [
              {
                "description": "string",
                "name": "string"
              }
            ]
          }
        ]
      },
      "created_at": "2019-08-24T14:15:22Z",
      "diff_status": {
        "additions": 0,
        "approved": true,
        "author_avatar_url": "string",
        "author_login": "string",
        "base_branch": "string",
        "changed_files": 0,
        "changes_requested": true,
        "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
        "commits": 0,
        "deletions": 0,
        "head_branch": "string",
        "pr_number": 0,
        "pull_request_draft": true,
        "pull_request_state": "string",
        "pull_request_title": "string",
        "refreshed_at": "2019-08-24T14:15:22Z",
        "reviewer_count": 0,
        "stale_at": "2019-08-24T14:15:22Z",
        "url": "string"
      },
      "files": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "mime_type": "string",
          "name": "string",
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
          "size_bytes": 0
        }
      ],
      "has_unread": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "inline_mcp_servers": [
        {
          "allow_in_subagents": true,
          "created_at": "2019-08-24T14:15:22Z",
          "forward_coder_headers": true,
          "has_custom_headers": true,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "slug": "string",
          "tool_allow_list": [
            "string"
          ],
          "tool_deny_list": [
            "string"
          ],
          "updated_at": "2019-08-24T14:15:22Z",
          "url": "string"
        }
      ],
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "last_error": {
        "detail": "string",
        "kind": "generic",
        "message": "string",
        "provider": "string",
        "retryable": true,
        "status_code": 0
      },
      "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
      "last_reasoning_effort": "string",
      "last_turn_summary": "string",
      "mcp_server_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "owner_name": "string",
      "owner_username": "string",
      "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
      "pin_order": 0,
      "plan_mode": "plan",
      "queued_for_capacity": true,
      "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
      "shared": true,
      "status": "waiting",
      "summary": "string",
      "title": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "warnings": [
        "string"
      ],
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ],
  "client_type": "ui",
  "context": {
    "dirty": true,
    "dirty_since": "2019-08-24T14:15:22Z",
    "error": "string",
    "resources": [
      {
        "error": "string",
        "kind": "instruction_file",
        "size_bytes": 0,
        "skill_description": "string",
        "skill_name": "string",
        "source": "string",
        "status": "ok",
        "tools": [
          {
            "description": "string",
            "name": "string"
          }
        ]
      }
    ]
  },
  "created_at": "2019-08-24T14:15:22Z",
  "diff_status": {
    "additions": 0,
    "approved": true,
    "author_avatar_url": "string",
    "author_login": "string",
    "base_branch": "string",
    "changed_files": 0,
    "changes_requested": true,
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "commits": 0,
    "deletions": 0,
    "head_branch": "string",
    "pr_number": 0,
    "pull_request_draft": true,
    "pull_request_state": "string",
    "pull_request_title": "string",
    "refreshed_at": "2019-08-24T14:15:22Z",
    "reviewer_count": 0,
    "stale_at": "2019-08-24T14:15:22Z",
    "url": "string"
  },
  "files": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "mime_type": "string",
      "name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "size_bytes": 0
    }
  ],
  "has_unread": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "created_at": "2019-08-24T14:15:22Z",
      "forward_coder_headers": true,
      "has_custom_headers": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "updated_at": "2019-08-24T14:15:22Z",
      "url": "string"
    }
  ],
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "last_error": {
    "detail": "string",
    "kind": "generic",
    "message": "string",
    "provider": "string",
    "retryable": true,
    "status_code": 0
  },
  "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
  "last_reasoning_effort": "string",
  "last_turn_summary": "string",
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "owner_username": "string",
  "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
  "pin_order": 0,
  "plan_mode": "plan",
  "queued_for_capacity": true,
  "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
  "shared": true,
  "status": "waiting",
  "summary": "string",
  "title": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "string"
  ],
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                                 | Description                  | Schema                                           |
|--------|-------------------------------------------------------------------------|------------------------------|--------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)            | Created                      | [codersdk.Chat](schemas.md#codersdkchat)         |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 256 KiB | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List chats by workspace

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/by-workspace \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/by-workspace`

### Parameters

| Name            | In    | Type   | Required | Description                   |
|-----------------|-------|--------|----------|-------------------------------|
| `workspace_ids` | query | string | false    | Comma-separated workspace IDs |

### Example responses

> 200 Response

```json
{
  "property1": "string",
  "property2": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                       |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [coderd.chatsByWorkspaceResponse](schemas.md#coderdchatsbyworkspaceresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat auto archive days

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/auto-archive-days \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/auto-archive-days`

### Example responses

> 200 Response

```json
{
  "auto_archive_days": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                 |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatAutoArchiveDaysResponse](schemas.md#codersdkchatautoarchivedaysresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update chat auto archive days

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/auto-archive-days \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/auto-archive-days`

> Body parameter

```json
{
  "auto_archive_days": 0
}
```

### Parameters

| Name   | In   | Type                                                                                             | Required | Description  |
|--------|------|--------------------------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UpdateChatAutoArchiveDaysRequest](schemas.md#codersdkupdatechatautoarchivedaysrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat debug logging setting

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/debug-logging \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/debug-logging`

### Example responses

> 200 Response

```json
{
  "allow_users": true,
  "forced_by_deployment": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                     |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatDebugLoggingAdminSettings](schemas.md#codersdkchatdebugloggingadminsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update chat debug logging setting

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/debug-logging \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/debug-logging`

> Body parameter

```json
{
  "allow_users": true
}
```

### Parameters

| Name   | In   | Type                                                                                                           | Required | Description  |
|--------|------|----------------------------------------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UpdateChatDebugLoggingAllowUsersRequest](schemas.md#codersdkupdatechatdebugloggingallowusersrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat debug retention days

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/debug-retention-days \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/debug-retention-days`

### Example responses

> 200 Response

```json
{
  "debug_retention_days": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatDebugRetentionDaysResponse](schemas.md#codersdkchatdebugretentiondaysresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update chat debug retention days

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/debug-retention-days \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/debug-retention-days`

> Body parameter

```json
{
  "debug_retention_days": 0
}
```

### Parameters

| Name   | In   | Type                                                                                                   | Required | Description  |
|--------|------|--------------------------------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UpdateChatDebugRetentionDaysRequest](schemas.md#codersdkupdatechatdebugretentiondaysrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat personal model override settings

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/personal-model-overrides \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/personal-model-overrides`

### Example responses

> 200 Response

```json
{
  "allow_users": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                                         |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatPersonalModelOverridesAdminSettings](schemas.md#codersdkchatpersonalmodeloverridesadminsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update chat personal model override settings

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/personal-model-overrides \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/personal-model-overrides`

> Body parameter

```json
{
  "allow_users": true
}
```

### Parameters

| Name   | In   | Type                                                                                                                                     | Required | Description  |
|--------|------|------------------------------------------------------------------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UpdateChatPersonalModelOverridesAdminSettingsRequest](schemas.md#codersdkupdatechatpersonalmodeloverridesadminsettingsrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat plan mode instructions

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/plan-mode-instructions \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/plan-mode-instructions`

### Example responses

> 200 Response

```json
{
  "plan_mode_instructions": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatPlanModeInstructionsResponse](schemas.md#codersdkchatplanmodeinstructionsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update chat plan mode instructions

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/plan-mode-instructions \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/plan-mode-instructions`

> Body parameter

```json
{
  "plan_mode_instructions": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                                       | Required | Description  |
|--------|------|------------------------------------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UpdateChatPlanModeInstructionsRequest](schemas.md#codersdkupdatechatplanmodeinstructionsrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat system prompt

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/system-prompt \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/system-prompt`

### Example responses

> 200 Response

```json
{
  "default_system_prompt": "string",
  "include_default_system_prompt": true,
  "system_prompt": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatSystemPromptResponse](schemas.md#codersdkchatsystempromptresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update chat system prompt

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/system-prompt \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/system-prompt`

> Body parameter

```json
{
  "include_default_system_prompt": true,
  "system_prompt": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                       | Required | Description  |
|--------|------|--------------------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UpdateChatSystemPromptRequest](schemas.md#codersdkupdatechatsystempromptrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user chat debug logging setting

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/user-debug-logging \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/user-debug-logging`

### Example responses

> 200 Response

```json
{
  "debug_logging_enabled": true,
  "forced_by_deployment": true,
  "user_toggle_allowed": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserChatDebugLoggingSettings](schemas.md#codersdkuserchatdebugloggingsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user chat debug logging setting

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/user-debug-logging \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/user-debug-logging`

> Body parameter

```json
{
  "debug_logging_enabled": true
}
```

### Parameters

| Name   | In   | Type                                                                                               | Required | Description  |
|--------|------|----------------------------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UpdateUserChatDebugLoggingRequest](schemas.md#codersdkupdateuserchatdebugloggingrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user chat custom prompt

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/user-prompt \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/user-prompt`

### Example responses

> 200 Response

```json
{
  "custom_prompt": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserChatCustomPrompt](schemas.md#codersdkuserchatcustomprompt) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user chat custom prompt

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/user-prompt \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/user-prompt`

> Body parameter

```json
{
  "custom_prompt": "string"
}
```

### Parameters

| Name   | In   | Type                                                                     | Required | Description  |
|--------|------|--------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UserChatCustomPrompt](schemas.md#codersdkuserchatcustomprompt) | true     | Request body |

### Example responses

> 200 Response

```json
{
  "custom_prompt": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserChatCustomPrompt](schemas.md#codersdkuserchatcustomprompt) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat workspace time to live

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/config/workspace-ttl \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/config/workspace-ttl`

### Example responses

> 200 Response

```json
{
  "workspace_ttl_ms": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatWorkspaceTTLResponse](schemas.md#codersdkchatworkspacettlresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update chat workspace time to live

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/config/workspace-ttl \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/config/workspace-ttl`

> Body parameter

```json
{
  "workspace_ttl_ms": 0
}
```

### Parameters

| Name   | In   | Type                                                                                       | Required | Description  |
|--------|------|--------------------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.UpdateChatWorkspaceTTLRequest](schemas.md#codersdkupdatechatworkspacettlrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Upload chat file

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats/files?organization=497f6eca-6276-4993-bfeb-53cbbbba6f08 \
  -H 'Content-Type: image/png' \
  -H 'Accept: application/json' \
  -H 'Content-Disposition: attachment; filename="image.png"' \
  -H 'Coder-Session-Token: API_KEY' \
  --data-binary '@image.png'
```

`POST /api/v2/chats/files`

### Parameters

| Name                  | In     | Type         | Required | Description                                   |
|-----------------------|--------|--------------|----------|-----------------------------------------------|
| `organization`        | query  | string(uuid) | true     | Organization ID                               |
| `Content-Disposition` | header | string       | true     | Attachment disposition carrying the file name |
| `body`                | body   | string       | true     | Raw file binary data                          |

### Example responses

> 201 Response

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}
```

### Responses

| Status | Meaning                                                                 | Description                 | Schema                                                                       |
|--------|-------------------------------------------------------------------------|-----------------------------|------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)            | Created                     | [codersdk.UploadChatFileResponse](schemas.md#codersdkuploadchatfileresponse) |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 10 MiB | [codersdk.Response](schemas.md#codersdkresponse)                             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat file

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/files/{file} \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/files/{file}`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `file` | path | string(uuid) | true     | File ID     |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Watch chat events for a user via WebSockets

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/watch \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/watch`

### Example responses

> 200 Response

```json
{
  "chat": {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "archived": true,
    "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
    "children": [
      {}
    ],
    "client_type": "ui",
    "context": {
      "dirty": true,
      "dirty_since": "2019-08-24T14:15:22Z",
      "error": "string",
      "resources": [
        {
          "error": "string",
          "kind": "instruction_file",
          "size_bytes": 0,
          "skill_description": "string",
          "skill_name": "string",
          "source": "string",
          "status": "ok",
          "tools": [
            {
              "description": "string",
              "name": "string"
            }
          ]
        }
      ]
    },
    "created_at": "2019-08-24T14:15:22Z",
    "diff_status": {
      "additions": 0,
      "approved": true,
      "author_avatar_url": "string",
      "author_login": "string",
      "base_branch": "string",
      "changed_files": 0,
      "changes_requested": true,
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "commits": 0,
      "deletions": 0,
      "head_branch": "string",
      "pr_number": 0,
      "pull_request_draft": true,
      "pull_request_state": "string",
      "pull_request_title": "string",
      "refreshed_at": "2019-08-24T14:15:22Z",
      "reviewer_count": 0,
      "stale_at": "2019-08-24T14:15:22Z",
      "url": "string"
    },
    "files": [
      {
        "created_at": "2019-08-24T14:15:22Z",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "mime_type": "string",
        "name": "string",
        "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
        "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
        "size_bytes": 0
      }
    ],
    "has_unread": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "inline_mcp_servers": [
      {
        "allow_in_subagents": true,
        "created_at": "2019-08-24T14:15:22Z",
        "forward_coder_headers": true,
        "has_custom_headers": true,
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "slug": "string",
        "tool_allow_list": [
          "string"
        ],
        "tool_deny_list": [
          "string"
        ],
        "updated_at": "2019-08-24T14:15:22Z",
        "url": "string"
      }
    ],
    "labels": {
      "property1": "string",
      "property2": "string"
    },
    "last_error": {
      "detail": "string",
      "kind": "generic",
      "message": "string",
      "provider": "string",
      "retryable": true,
      "status_code": 0
    },
    "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
    "last_reasoning_effort": "string",
    "last_turn_summary": "string",
    "mcp_server_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
    "owner_name": "string",
    "owner_username": "string",
    "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
    "pin_order": 0,
    "plan_mode": "plan",
    "queued_for_capacity": true,
    "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
    "shared": true,
    "status": "waiting",
    "summary": "string",
    "title": "string",
    "updated_at": "2019-08-24T14:15:22Z",
    "warnings": [
      "string"
    ],
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  },
  "kind": "status_change",
  "tool_calls": [
    {
      "args": "string",
      "tool_call_id": "string",
      "tool_name": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatWatchEvent](schemas.md#codersdkchatwatchevent) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/{chat} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/{chat}`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Example responses

> 200 Response

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "archived": true,
  "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
  "children": [
    {
      "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
      "archived": true,
      "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
      "children": [],
      "client_type": "ui",
      "context": {
        "dirty": true,
        "dirty_since": "2019-08-24T14:15:22Z",
        "error": "string",
        "resources": [
          {
            "error": "string",
            "kind": "instruction_file",
            "size_bytes": 0,
            "skill_description": "string",
            "skill_name": "string",
            "source": "string",
            "status": "ok",
            "tools": [
              {
                "description": "string",
                "name": "string"
              }
            ]
          }
        ]
      },
      "created_at": "2019-08-24T14:15:22Z",
      "diff_status": {
        "additions": 0,
        "approved": true,
        "author_avatar_url": "string",
        "author_login": "string",
        "base_branch": "string",
        "changed_files": 0,
        "changes_requested": true,
        "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
        "commits": 0,
        "deletions": 0,
        "head_branch": "string",
        "pr_number": 0,
        "pull_request_draft": true,
        "pull_request_state": "string",
        "pull_request_title": "string",
        "refreshed_at": "2019-08-24T14:15:22Z",
        "reviewer_count": 0,
        "stale_at": "2019-08-24T14:15:22Z",
        "url": "string"
      },
      "files": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "mime_type": "string",
          "name": "string",
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
          "size_bytes": 0
        }
      ],
      "has_unread": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "inline_mcp_servers": [
        {
          "allow_in_subagents": true,
          "created_at": "2019-08-24T14:15:22Z",
          "forward_coder_headers": true,
          "has_custom_headers": true,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "slug": "string",
          "tool_allow_list": [
            "string"
          ],
          "tool_deny_list": [
            "string"
          ],
          "updated_at": "2019-08-24T14:15:22Z",
          "url": "string"
        }
      ],
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "last_error": {
        "detail": "string",
        "kind": "generic",
        "message": "string",
        "provider": "string",
        "retryable": true,
        "status_code": 0
      },
      "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
      "last_reasoning_effort": "string",
      "last_turn_summary": "string",
      "mcp_server_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "owner_name": "string",
      "owner_username": "string",
      "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
      "pin_order": 0,
      "plan_mode": "plan",
      "queued_for_capacity": true,
      "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
      "shared": true,
      "status": "waiting",
      "summary": "string",
      "title": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "warnings": [
        "string"
      ],
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ],
  "client_type": "ui",
  "context": {
    "dirty": true,
    "dirty_since": "2019-08-24T14:15:22Z",
    "error": "string",
    "resources": [
      {
        "error": "string",
        "kind": "instruction_file",
        "size_bytes": 0,
        "skill_description": "string",
        "skill_name": "string",
        "source": "string",
        "status": "ok",
        "tools": [
          {
            "description": "string",
            "name": "string"
          }
        ]
      }
    ]
  },
  "created_at": "2019-08-24T14:15:22Z",
  "diff_status": {
    "additions": 0,
    "approved": true,
    "author_avatar_url": "string",
    "author_login": "string",
    "base_branch": "string",
    "changed_files": 0,
    "changes_requested": true,
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "commits": 0,
    "deletions": 0,
    "head_branch": "string",
    "pr_number": 0,
    "pull_request_draft": true,
    "pull_request_state": "string",
    "pull_request_title": "string",
    "refreshed_at": "2019-08-24T14:15:22Z",
    "reviewer_count": 0,
    "stale_at": "2019-08-24T14:15:22Z",
    "url": "string"
  },
  "files": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "mime_type": "string",
      "name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "size_bytes": 0
    }
  ],
  "has_unread": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "created_at": "2019-08-24T14:15:22Z",
      "forward_coder_headers": true,
      "has_custom_headers": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "updated_at": "2019-08-24T14:15:22Z",
      "url": "string"
    }
  ],
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "last_error": {
    "detail": "string",
    "kind": "generic",
    "message": "string",
    "provider": "string",
    "retryable": true,
    "status_code": 0
  },
  "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
  "last_reasoning_effort": "string",
  "last_turn_summary": "string",
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "owner_username": "string",
  "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
  "pin_order": 0,
  "plan_mode": "plan",
  "queued_for_capacity": true,
  "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
  "shared": true,
  "status": "waiting",
  "summary": "string",
  "title": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "string"
  ],
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Chat](schemas.md#codersdkchat) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update chat

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/chats/{chat} \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/chats/{chat}`

> Body parameter

```json
{
  "archived": true,
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "pin_order": 0,
  "plan_mode": "plan",
  "read": true,
  "title": "string",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Parameters

| Name   | In   | Type                                                               | Required | Description         |
|--------|------|--------------------------------------------------------------------|----------|---------------------|
| `chat` | path | string(uuid)                                                       | true     | Chat ID             |
| `body` | body | [codersdk.UpdateChatRequest](schemas.md#codersdkupdatechatrequest) | true     | Update chat request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Refresh chat context

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/chats/{chat}/context \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/chats/{chat}/context`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Example responses

> 200 Response

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "archived": true,
  "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
  "children": [
    {
      "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
      "archived": true,
      "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
      "children": [],
      "client_type": "ui",
      "context": {
        "dirty": true,
        "dirty_since": "2019-08-24T14:15:22Z",
        "error": "string",
        "resources": [
          {
            "error": "string",
            "kind": "instruction_file",
            "size_bytes": 0,
            "skill_description": "string",
            "skill_name": "string",
            "source": "string",
            "status": "ok",
            "tools": [
              {
                "description": "string",
                "name": "string"
              }
            ]
          }
        ]
      },
      "created_at": "2019-08-24T14:15:22Z",
      "diff_status": {
        "additions": 0,
        "approved": true,
        "author_avatar_url": "string",
        "author_login": "string",
        "base_branch": "string",
        "changed_files": 0,
        "changes_requested": true,
        "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
        "commits": 0,
        "deletions": 0,
        "head_branch": "string",
        "pr_number": 0,
        "pull_request_draft": true,
        "pull_request_state": "string",
        "pull_request_title": "string",
        "refreshed_at": "2019-08-24T14:15:22Z",
        "reviewer_count": 0,
        "stale_at": "2019-08-24T14:15:22Z",
        "url": "string"
      },
      "files": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "mime_type": "string",
          "name": "string",
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
          "size_bytes": 0
        }
      ],
      "has_unread": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "inline_mcp_servers": [
        {
          "allow_in_subagents": true,
          "created_at": "2019-08-24T14:15:22Z",
          "forward_coder_headers": true,
          "has_custom_headers": true,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "slug": "string",
          "tool_allow_list": [
            "string"
          ],
          "tool_deny_list": [
            "string"
          ],
          "updated_at": "2019-08-24T14:15:22Z",
          "url": "string"
        }
      ],
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "last_error": {
        "detail": "string",
        "kind": "generic",
        "message": "string",
        "provider": "string",
        "retryable": true,
        "status_code": 0
      },
      "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
      "last_reasoning_effort": "string",
      "last_turn_summary": "string",
      "mcp_server_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "owner_name": "string",
      "owner_username": "string",
      "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
      "pin_order": 0,
      "plan_mode": "plan",
      "queued_for_capacity": true,
      "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
      "shared": true,
      "status": "waiting",
      "summary": "string",
      "title": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "warnings": [
        "string"
      ],
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ],
  "client_type": "ui",
  "context": {
    "dirty": true,
    "dirty_since": "2019-08-24T14:15:22Z",
    "error": "string",
    "resources": [
      {
        "error": "string",
        "kind": "instruction_file",
        "size_bytes": 0,
        "skill_description": "string",
        "skill_name": "string",
        "source": "string",
        "status": "ok",
        "tools": [
          {
            "description": "string",
            "name": "string"
          }
        ]
      }
    ]
  },
  "created_at": "2019-08-24T14:15:22Z",
  "diff_status": {
    "additions": 0,
    "approved": true,
    "author_avatar_url": "string",
    "author_login": "string",
    "base_branch": "string",
    "changed_files": 0,
    "changes_requested": true,
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "commits": 0,
    "deletions": 0,
    "head_branch": "string",
    "pr_number": 0,
    "pull_request_draft": true,
    "pull_request_state": "string",
    "pull_request_title": "string",
    "refreshed_at": "2019-08-24T14:15:22Z",
    "reviewer_count": 0,
    "stale_at": "2019-08-24T14:15:22Z",
    "url": "string"
  },
  "files": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "mime_type": "string",
      "name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "size_bytes": 0
    }
  ],
  "has_unread": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "created_at": "2019-08-24T14:15:22Z",
      "forward_coder_headers": true,
      "has_custom_headers": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "updated_at": "2019-08-24T14:15:22Z",
      "url": "string"
    }
  ],
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "last_error": {
    "detail": "string",
    "kind": "generic",
    "message": "string",
    "provider": "string",
    "retryable": true,
    "status_code": 0
  },
  "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
  "last_reasoning_effort": "string",
  "last_turn_summary": "string",
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "owner_username": "string",
  "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
  "pin_order": 0,
  "plan_mode": "plan",
  "queued_for_capacity": true,
  "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
  "shared": true,
  "status": "waiting",
  "summary": "string",
  "title": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "string"
  ],
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Chat](schemas.md#codersdkchat) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat cost

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/{chat}/cost \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/{chat}/cost`

Cost covers the whole chat tree: the root chat plus every
subagent chat beneath it. Requesting cost for a subagent chat
returns that same total.

Cost is derived from AI Gateway data, which is subject to its
own retention period, 60 days by default, configured
independently of chat retention. Spend for requests older than
that period is no longer reported, so a chat whose requests
have all been purged reports zero cost.

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Example responses

> 200 Response

```json
{
  "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
  "request_count": 0,
  "total_cost_micros": 0,
  "unpriced_request_count": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatCost](schemas.md#codersdkchatcost) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get chat diff contents

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/{chat}/diff \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/{chat}/diff`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Example responses

> 200 Response

```json
{
  "branch": "string",
  "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
  "diff": "string",
  "provider": "string",
  "pull_request_url": "string",
  "remote_origin": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatDiffContents](schemas.md#codersdkchatdiffcontents) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Interrupt chat

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats/{chat}/interrupt \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/chats/{chat}/interrupt`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Example responses

> 200 Response

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "archived": true,
  "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
  "children": [
    {
      "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
      "archived": true,
      "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
      "children": [],
      "client_type": "ui",
      "context": {
        "dirty": true,
        "dirty_since": "2019-08-24T14:15:22Z",
        "error": "string",
        "resources": [
          {
            "error": "string",
            "kind": "instruction_file",
            "size_bytes": 0,
            "skill_description": "string",
            "skill_name": "string",
            "source": "string",
            "status": "ok",
            "tools": [
              {
                "description": "string",
                "name": "string"
              }
            ]
          }
        ]
      },
      "created_at": "2019-08-24T14:15:22Z",
      "diff_status": {
        "additions": 0,
        "approved": true,
        "author_avatar_url": "string",
        "author_login": "string",
        "base_branch": "string",
        "changed_files": 0,
        "changes_requested": true,
        "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
        "commits": 0,
        "deletions": 0,
        "head_branch": "string",
        "pr_number": 0,
        "pull_request_draft": true,
        "pull_request_state": "string",
        "pull_request_title": "string",
        "refreshed_at": "2019-08-24T14:15:22Z",
        "reviewer_count": 0,
        "stale_at": "2019-08-24T14:15:22Z",
        "url": "string"
      },
      "files": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "mime_type": "string",
          "name": "string",
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
          "size_bytes": 0
        }
      ],
      "has_unread": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "inline_mcp_servers": [
        {
          "allow_in_subagents": true,
          "created_at": "2019-08-24T14:15:22Z",
          "forward_coder_headers": true,
          "has_custom_headers": true,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "slug": "string",
          "tool_allow_list": [
            "string"
          ],
          "tool_deny_list": [
            "string"
          ],
          "updated_at": "2019-08-24T14:15:22Z",
          "url": "string"
        }
      ],
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "last_error": {
        "detail": "string",
        "kind": "generic",
        "message": "string",
        "provider": "string",
        "retryable": true,
        "status_code": 0
      },
      "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
      "last_reasoning_effort": "string",
      "last_turn_summary": "string",
      "mcp_server_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "owner_name": "string",
      "owner_username": "string",
      "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
      "pin_order": 0,
      "plan_mode": "plan",
      "queued_for_capacity": true,
      "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
      "shared": true,
      "status": "waiting",
      "summary": "string",
      "title": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "warnings": [
        "string"
      ],
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ],
  "client_type": "ui",
  "context": {
    "dirty": true,
    "dirty_since": "2019-08-24T14:15:22Z",
    "error": "string",
    "resources": [
      {
        "error": "string",
        "kind": "instruction_file",
        "size_bytes": 0,
        "skill_description": "string",
        "skill_name": "string",
        "source": "string",
        "status": "ok",
        "tools": [
          {
            "description": "string",
            "name": "string"
          }
        ]
      }
    ]
  },
  "created_at": "2019-08-24T14:15:22Z",
  "diff_status": {
    "additions": 0,
    "approved": true,
    "author_avatar_url": "string",
    "author_login": "string",
    "base_branch": "string",
    "changed_files": 0,
    "changes_requested": true,
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "commits": 0,
    "deletions": 0,
    "head_branch": "string",
    "pr_number": 0,
    "pull_request_draft": true,
    "pull_request_state": "string",
    "pull_request_title": "string",
    "refreshed_at": "2019-08-24T14:15:22Z",
    "reviewer_count": 0,
    "stale_at": "2019-08-24T14:15:22Z",
    "url": "string"
  },
  "files": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "mime_type": "string",
      "name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "size_bytes": 0
    }
  ],
  "has_unread": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "created_at": "2019-08-24T14:15:22Z",
      "forward_coder_headers": true,
      "has_custom_headers": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "updated_at": "2019-08-24T14:15:22Z",
      "url": "string"
    }
  ],
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "last_error": {
    "detail": "string",
    "kind": "generic",
    "message": "string",
    "provider": "string",
    "retryable": true,
    "status_code": 0
  },
  "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
  "last_reasoning_effort": "string",
  "last_turn_summary": "string",
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "owner_username": "string",
  "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
  "pin_order": 0,
  "plan_mode": "plan",
  "queued_for_capacity": true,
  "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
  "shared": true,
  "status": "waiting",
  "summary": "string",
  "title": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "string"
  ],
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Chat](schemas.md#codersdkchat) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List chat messages

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/{chat}/messages \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/{chat}/messages`

### Parameters

| Name        | In    | Type         | Required | Description                          |
|-------------|-------|--------------|----------|--------------------------------------|
| `chat`      | path  | string(uuid) | true     | Chat ID                              |
| `before_id` | query | integer      | false    | Return messages with id < before_id  |
| `after_id`  | query | integer      | false    | Return messages with id > after_id   |
| `limit`     | query | integer      | false    | Page size, 1 to 200. Defaults to 50. |

### Example responses

> 200 Response

```json
{
  "has_more": true,
  "messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
      "queued_message_id": 0,
      "role": "system",
      "usage": {
        "cache_creation_tokens": 0,
        "cache_read_tokens": 0,
        "context_limit": 0,
        "input_tokens": 0,
        "output_tokens": 0,
        "reasoning_tokens": 0,
        "total_tokens": 0
      }
    }
  ],
  "queued_messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatMessagesResponse](schemas.md#codersdkchatmessagesresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Send chat message

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats/{chat}/messages \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/chats/{chat}/messages`

> Body parameter

```json
{
  "busy_behavior": "queue",
  "content": [
    {
      "content": "string",
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "start_line": 0,
      "text": "string",
      "type": "text",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    }
  ],
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "forward_coder_headers": true,
      "headers": {
        "property1": "string",
        "property2": "string"
      },
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "url": "string"
    }
  ],
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
  "plan_mode": "plan",
  "reasoning_effort": "string"
}
```

### Parameters

| Name   | In   | Type                                                                             | Required | Description                 |
|--------|------|----------------------------------------------------------------------------------|----------|-----------------------------|
| `chat` | path | string(uuid)                                                                     | true     | Chat ID                     |
| `body` | body | [codersdk.CreateChatMessageRequest](schemas.md#codersdkcreatechatmessagerequest) | true     | Create chat message request |

### Example responses

> 200 Response

```json
{
  "message": {
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "content": [
      {
        "args": [
          0
        ],
        "args_delta": "string",
        "completed_at": "2019-08-24T14:15:22Z",
        "content": "string",
        "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
        "context_file_content": "string",
        "context_file_directory": "string",
        "context_file_os": "string",
        "context_file_path": "string",
        "context_file_skill_meta_file": "string",
        "context_file_truncated": true,
        "created_at": "2019-08-24T14:15:22Z",
        "data": [
          0
        ],
        "end_line": 0,
        "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
        "file_name": "string",
        "hook_rewritten": true,
        "is_error": true,
        "is_media": true,
        "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
        "media_type": "string",
        "name": "string",
        "parsed_commands": [
          [
            "string"
          ]
        ],
        "provider_executed": true,
        "provider_metadata": [
          0
        ],
        "reasoning_delta": "string",
        "result": [
          0
        ],
        "result_delta": "string",
        "result_reset": true,
        "skill_description": "string",
        "skill_dir": "string",
        "skill_name": "string",
        "source_id": "string",
        "start_line": 0,
        "text": "string",
        "title": "string",
        "tool_call_id": "string",
        "tool_name": "string",
        "type": "text",
        "url": "string",
        "workspace_file_media_type": "string",
        "workspace_file_name": "string",
        "workspace_file_path": "string",
        "workspace_file_size": 0,
        "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
    "id": 0,
    "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
    "queued_message_id": 0,
    "role": "system",
    "usage": {
      "cache_creation_tokens": 0,
      "cache_read_tokens": 0,
      "context_limit": 0,
      "input_tokens": 0,
      "output_tokens": 0,
      "reasoning_tokens": 0,
      "total_tokens": 0
    }
  },
  "messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
      "queued_message_id": 0,
      "role": "system",
      "usage": {
        "cache_creation_tokens": 0,
        "cache_read_tokens": 0,
        "context_limit": 0,
        "input_tokens": 0,
        "output_tokens": 0,
        "reasoning_tokens": 0,
        "total_tokens": 0
      }
    }
  ],
  "queued": true,
  "queued_message": {
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "content": [
      {
        "args": [
          0
        ],
        "args_delta": "string",
        "completed_at": "2019-08-24T14:15:22Z",
        "content": "string",
        "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
        "context_file_content": "string",
        "context_file_directory": "string",
        "context_file_os": "string",
        "context_file_path": "string",
        "context_file_skill_meta_file": "string",
        "context_file_truncated": true,
        "created_at": "2019-08-24T14:15:22Z",
        "data": [
          0
        ],
        "end_line": 0,
        "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
        "file_name": "string",
        "hook_rewritten": true,
        "is_error": true,
        "is_media": true,
        "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
        "media_type": "string",
        "name": "string",
        "parsed_commands": [
          [
            "string"
          ]
        ],
        "provider_executed": true,
        "provider_metadata": [
          0
        ],
        "reasoning_delta": "string",
        "result": [
          0
        ],
        "result_delta": "string",
        "result_reset": true,
        "skill_description": "string",
        "skill_dir": "string",
        "skill_name": "string",
        "source_id": "string",
        "start_line": 0,
        "text": "string",
        "title": "string",
        "tool_call_id": "string",
        "tool_name": "string",
        "type": "text",
        "url": "string",
        "workspace_file_media_type": "string",
        "workspace_file_name": "string",
        "workspace_file_path": "string",
        "workspace_file_size": 0,
        "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "id": 0,
    "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205"
  },
  "warnings": [
    "string"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                             |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.CreateChatMessageResponse](schemas.md#codersdkcreatechatmessageresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Edit chat message

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/chats/{chat}/messages/{message} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/chats/{chat}/messages/{message}`

> Body parameter

```json
{
  "content": [
    {
      "content": "string",
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "start_line": 0,
      "text": "string",
      "type": "text",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    }
  ],
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
  "reasoning_effort": "string"
}
```

### Parameters

| Name      | In   | Type                                                                         | Required | Description               |
|-----------|------|------------------------------------------------------------------------------|----------|---------------------------|
| `chat`    | path | string(uuid)                                                                 | true     | Chat ID                   |
| `message` | path | integer                                                                      | true     | Message ID                |
| `body`    | body | [codersdk.EditChatMessageRequest](schemas.md#codersdkeditchatmessagerequest) | true     | Edit chat message request |

### Example responses

> 200 Response

```json
{
  "deleted_message_ids": [
    0
  ],
  "message": {
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "content": [
      {
        "args": [
          0
        ],
        "args_delta": "string",
        "completed_at": "2019-08-24T14:15:22Z",
        "content": "string",
        "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
        "context_file_content": "string",
        "context_file_directory": "string",
        "context_file_os": "string",
        "context_file_path": "string",
        "context_file_skill_meta_file": "string",
        "context_file_truncated": true,
        "created_at": "2019-08-24T14:15:22Z",
        "data": [
          0
        ],
        "end_line": 0,
        "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
        "file_name": "string",
        "hook_rewritten": true,
        "is_error": true,
        "is_media": true,
        "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
        "media_type": "string",
        "name": "string",
        "parsed_commands": [
          [
            "string"
          ]
        ],
        "provider_executed": true,
        "provider_metadata": [
          0
        ],
        "reasoning_delta": "string",
        "result": [
          0
        ],
        "result_delta": "string",
        "result_reset": true,
        "skill_description": "string",
        "skill_dir": "string",
        "skill_name": "string",
        "source_id": "string",
        "start_line": 0,
        "text": "string",
        "title": "string",
        "tool_call_id": "string",
        "tool_name": "string",
        "type": "text",
        "url": "string",
        "workspace_file_media_type": "string",
        "workspace_file_name": "string",
        "workspace_file_path": "string",
        "workspace_file_size": 0,
        "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
    "id": 0,
    "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
    "queued_message_id": 0,
    "role": "system",
    "usage": {
      "cache_creation_tokens": 0,
      "cache_read_tokens": 0,
      "context_limit": 0,
      "input_tokens": 0,
      "output_tokens": 0,
      "reasoning_tokens": 0,
      "total_tokens": 0
    }
  },
  "messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
      "queued_message_id": 0,
      "role": "system",
      "usage": {
        "cache_creation_tokens": 0,
        "cache_read_tokens": 0,
        "context_limit": 0,
        "input_tokens": 0,
        "output_tokens": 0,
        "reasoning_tokens": 0,
        "total_tokens": 0
      }
    }
  ],
  "warnings": [
    "string"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                         |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.EditChatMessageResponse](schemas.md#codersdkeditchatmessageresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List chat user prompts

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/{chat}/prompts \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/{chat}/prompts`

Returns the user-authored prompts in a chat, newest first,
with each prompt's text parts concatenated in the order they
were authored. Used by the composer to power the up/down
arrow prompt-history cycle without paging through every
message in the chat.

### Parameters

| Name    | In    | Type         | Required | Description                                                                 |
|---------|-------|--------------|----------|-----------------------------------------------------------------------------|
| `chat`  | path  | string(uuid) | true     | Chat ID                                                                     |
| `limit` | query | integer      | false    | Page size, 0 to 2000. 0 (the default) means the server-side default of 500. |

### Example responses

> 200 Response

```json
{
  "prompts": [
    {
      "id": 0,
      "text": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                 |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ChatPromptsResponse](schemas.md#codersdkchatpromptsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete chat queued message

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/chats/{chat}/queue/{queuedMessage} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/chats/{chat}/queue/{queuedMessage}`

### Parameters

| Name            | In   | Type         | Required | Description       |
|-----------------|------|--------------|----------|-------------------|
| `chat`          | path | string(uuid) | true     | Chat ID           |
| `queuedMessage` | path | integer      | true     | Queued message ID |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Promote chat queued message

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats/{chat}/queue/{queuedMessage}/promote \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/chats/{chat}/queue/{queuedMessage}/promote`

### Parameters

| Name            | In   | Type         | Required | Description       |
|-----------------|------|--------------|----------|-------------------|
| `chat`          | path | string(uuid) | true     | Chat ID           |
| `queuedMessage` | path | integer      | true     | Queued message ID |

### Example responses

> 202 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                       | Description | Schema                                           |
|--------|---------------------------------------------------------------|-------------|--------------------------------------------------|
| 202    | [Accepted](https://tools.ietf.org/html/rfc7231#section-6.3.3) | Accepted    | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Reconcile invalid chat state

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats/{chat}/reconcile-invalid \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/chats/{chat}/reconcile-invalid`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Example responses

> 200 Response

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "archived": true,
  "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
  "children": [
    {
      "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
      "archived": true,
      "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
      "children": [],
      "client_type": "ui",
      "context": {
        "dirty": true,
        "dirty_since": "2019-08-24T14:15:22Z",
        "error": "string",
        "resources": [
          {
            "error": "string",
            "kind": "instruction_file",
            "size_bytes": 0,
            "skill_description": "string",
            "skill_name": "string",
            "source": "string",
            "status": "ok",
            "tools": [
              {
                "description": "string",
                "name": "string"
              }
            ]
          }
        ]
      },
      "created_at": "2019-08-24T14:15:22Z",
      "diff_status": {
        "additions": 0,
        "approved": true,
        "author_avatar_url": "string",
        "author_login": "string",
        "base_branch": "string",
        "changed_files": 0,
        "changes_requested": true,
        "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
        "commits": 0,
        "deletions": 0,
        "head_branch": "string",
        "pr_number": 0,
        "pull_request_draft": true,
        "pull_request_state": "string",
        "pull_request_title": "string",
        "refreshed_at": "2019-08-24T14:15:22Z",
        "reviewer_count": 0,
        "stale_at": "2019-08-24T14:15:22Z",
        "url": "string"
      },
      "files": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "mime_type": "string",
          "name": "string",
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
          "size_bytes": 0
        }
      ],
      "has_unread": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "inline_mcp_servers": [
        {
          "allow_in_subagents": true,
          "created_at": "2019-08-24T14:15:22Z",
          "forward_coder_headers": true,
          "has_custom_headers": true,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "slug": "string",
          "tool_allow_list": [
            "string"
          ],
          "tool_deny_list": [
            "string"
          ],
          "updated_at": "2019-08-24T14:15:22Z",
          "url": "string"
        }
      ],
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "last_error": {
        "detail": "string",
        "kind": "generic",
        "message": "string",
        "provider": "string",
        "retryable": true,
        "status_code": 0
      },
      "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
      "last_reasoning_effort": "string",
      "last_turn_summary": "string",
      "mcp_server_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "owner_name": "string",
      "owner_username": "string",
      "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
      "pin_order": 0,
      "plan_mode": "plan",
      "queued_for_capacity": true,
      "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
      "shared": true,
      "status": "waiting",
      "summary": "string",
      "title": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "warnings": [
        "string"
      ],
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ],
  "client_type": "ui",
  "context": {
    "dirty": true,
    "dirty_since": "2019-08-24T14:15:22Z",
    "error": "string",
    "resources": [
      {
        "error": "string",
        "kind": "instruction_file",
        "size_bytes": 0,
        "skill_description": "string",
        "skill_name": "string",
        "source": "string",
        "status": "ok",
        "tools": [
          {
            "description": "string",
            "name": "string"
          }
        ]
      }
    ]
  },
  "created_at": "2019-08-24T14:15:22Z",
  "diff_status": {
    "additions": 0,
    "approved": true,
    "author_avatar_url": "string",
    "author_login": "string",
    "base_branch": "string",
    "changed_files": 0,
    "changes_requested": true,
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "commits": 0,
    "deletions": 0,
    "head_branch": "string",
    "pr_number": 0,
    "pull_request_draft": true,
    "pull_request_state": "string",
    "pull_request_title": "string",
    "refreshed_at": "2019-08-24T14:15:22Z",
    "reviewer_count": 0,
    "stale_at": "2019-08-24T14:15:22Z",
    "url": "string"
  },
  "files": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "mime_type": "string",
      "name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "size_bytes": 0
    }
  ],
  "has_unread": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "created_at": "2019-08-24T14:15:22Z",
      "forward_coder_headers": true,
      "has_custom_headers": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "updated_at": "2019-08-24T14:15:22Z",
      "url": "string"
    }
  ],
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "last_error": {
    "detail": "string",
    "kind": "generic",
    "message": "string",
    "provider": "string",
    "retryable": true,
    "status_code": 0
  },
  "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
  "last_reasoning_effort": "string",
  "last_turn_summary": "string",
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "owner_username": "string",
  "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
  "pin_order": 0,
  "plan_mode": "plan",
  "queued_for_capacity": true,
  "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
  "shared": true,
  "status": "waiting",
  "summary": "string",
  "title": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "string"
  ],
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Chat](schemas.md#codersdkchat) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Stream chat events via WebSockets

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/{chat}/stream \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/{chat}/stream`

### Parameters

| Name       | In    | Type         | Required | Description                                             |
|------------|-------|--------------|----------|---------------------------------------------------------|
| `chat`     | path  | string(uuid) | true     | Chat ID                                                 |
| `after_id` | query | integer      | false    | Skip snapshot messages with id at or before this cursor |

### Example responses

> 200 Response

```json
[
  {
    "action_required": {
      "tool_calls": [
        {
          "args": "string",
          "tool_call_id": "string",
          "tool_name": "string"
        }
      ]
    },
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "error": {
      "detail": "string",
      "kind": "generic",
      "message": "string",
      "provider": "string",
      "retryable": true,
      "status_code": 0
    },
    "message": {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
      "queued_message_id": 0,
      "role": "system",
      "usage": {
        "cache_creation_tokens": 0,
        "cache_read_tokens": 0,
        "context_limit": 0,
        "input_tokens": 0,
        "output_tokens": 0,
        "reasoning_tokens": 0,
        "total_tokens": 0
      }
    },
    "message_part": {
      "generation_attempt": 0,
      "history_version": 0,
      "part": {
        "args": [
          0
        ],
        "args_delta": "string",
        "completed_at": "2019-08-24T14:15:22Z",
        "content": "string",
        "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
        "context_file_content": "string",
        "context_file_directory": "string",
        "context_file_os": "string",
        "context_file_path": "string",
        "context_file_skill_meta_file": "string",
        "context_file_truncated": true,
        "created_at": "2019-08-24T14:15:22Z",
        "data": [
          0
        ],
        "end_line": 0,
        "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
        "file_name": "string",
        "hook_rewritten": true,
        "is_error": true,
        "is_media": true,
        "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
        "media_type": "string",
        "name": "string",
        "parsed_commands": [
          [
            "string"
          ]
        ],
        "provider_executed": true,
        "provider_metadata": [
          0
        ],
        "reasoning_delta": "string",
        "result": [
          0
        ],
        "result_delta": "string",
        "result_reset": true,
        "skill_description": "string",
        "skill_dir": "string",
        "skill_name": "string",
        "source_id": "string",
        "start_line": 0,
        "text": "string",
        "title": "string",
        "tool_call_id": "string",
        "tool_name": "string",
        "type": "text",
        "url": "string",
        "workspace_file_media_type": "string",
        "workspace_file_name": "string",
        "workspace_file_path": "string",
        "workspace_file_size": 0,
        "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
      },
      "role": "system",
      "seq": 0
    },
    "queued_messages": [
      {
        "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
        "content": [
          {
            "args": [
              0
            ],
            "args_delta": "string",
            "completed_at": "2019-08-24T14:15:22Z",
            "content": "string",
            "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
            "context_file_content": "string",
            "context_file_directory": "string",
            "context_file_os": "string",
            "context_file_path": "string",
            "context_file_skill_meta_file": "string",
            "context_file_truncated": true,
            "created_at": "2019-08-24T14:15:22Z",
            "data": [
              0
            ],
            "end_line": 0,
            "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
            "file_name": "string",
            "hook_rewritten": true,
            "is_error": true,
            "is_media": true,
            "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
            "media_type": "string",
            "name": "string",
            "parsed_commands": [
              [
                "string"
              ]
            ],
            "provider_executed": true,
            "provider_metadata": [
              0
            ],
            "reasoning_delta": "string",
            "result": [
              0
            ],
            "result_delta": "string",
            "result_reset": true,
            "skill_description": "string",
            "skill_dir": "string",
            "skill_name": "string",
            "source_id": "string",
            "start_line": 0,
            "text": "string",
            "title": "string",
            "tool_call_id": "string",
            "tool_name": "string",
            "type": "text",
            "url": "string",
            "workspace_file_media_type": "string",
            "workspace_file_name": "string",
            "workspace_file_path": "string",
            "workspace_file_size": 0,
            "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
          }
        ],
        "created_at": "2019-08-24T14:15:22Z",
        "id": 0,
        "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205"
      }
    ],
    "retry": {
      "attempt": 0,
      "delay_ms": 0,
      "error": "string",
      "kind": "generic",
      "provider": "string",
      "retrying_at": "2019-08-24T14:15:22Z",
      "status_code": 0
    },
    "status": {
      "status": "waiting"
    },
    "type": "message_part"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                  |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ChatStreamEvent](schemas.md#codersdkchatstreamevent) |

<h3 id="stream-chat-events-via-websockets-responseschema">Response Schema</h3>

Status Code **200**

| Name                               | Type                                                                             | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                                                                |
|------------------------------------|----------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                     | array                                                                            | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `» action_required`                | [codersdk.ChatStreamActionRequired](schemas.md#codersdkchatstreamactionrequired) | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» tool_calls`                    | array                                                                            | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» args`                         | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» tool_call_id`                 | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» tool_name`                    | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `» chat_id`                        | string(uuid)                                                                     | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `» error`                          | [codersdk.ChatError](schemas.md#codersdkchaterror)                               | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» detail`                        | string                                                                           | false    |              | Detail is optional provider-specific context shown alongside the normalized error message when available.                                                                                                                                                                                                                                                                                                  |
| `»» kind`                          | [codersdk.ChatErrorKind](schemas.md#codersdkchaterrorkind)                       | false    |              | Kind classifies the error for consistent client rendering.                                                                                                                                                                                                                                                                                                                                                 |
| `»» message`                       | string                                                                           | false    |              | Message is the normalized, user-facing error message.                                                                                                                                                                                                                                                                                                                                                      |
| `»» provider`                      | string                                                                           | false    |              | Provider identifies the upstream model provider when known.                                                                                                                                                                                                                                                                                                                                                |
| `»» retryable`                     | boolean                                                                          | false    |              | Retryable reports whether the underlying error is transient.                                                                                                                                                                                                                                                                                                                                               |
| `»» status_code`                   | integer                                                                          | false    |              | Status code is the best-effort upstream HTTP status code.                                                                                                                                                                                                                                                                                                                                                  |
| `» message`                        | [codersdk.ChatMessage](schemas.md#codersdkchatmessage)                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» chat_id`                       | string(uuid)                                                                     | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» content`                       | array                                                                            | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» args`                         | array                                                                            | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» args_delta`                   | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» completed_at`                 | string(date-time)                                                                | false    |              | Completed at is the time a reasoning part finished streaming, so reasoning duration can be computed as completed_at minus created_at. For interrupted reasoning, this is the interruption time. Absent when reasoning timestamp data was not recorded (e.g. messages persisted before this feature was added).                                                                                             |
| `»»» content`                      | string                                                                           | false    |              | The code content from the diff that was commented on.                                                                                                                                                                                                                                                                                                                                                      |
| `»»» context_file_agent_id`        | string(uuid)                                                                     | false    |              | Context file agent ID is the workspace agent that provided this context file. Used to detect when the agent changes (e.g. workspace rebuilt) so instruction files can be re-persisted with fresh content.                                                                                                                                                                                                  |
| `»»» context_file_content`         | string                                                                           | false    |              | Context file content holds the file content sent to the LLM. Internal only: stripped before API responses to keep payloads small. The backend reads it when building the prompt via partsToMessageParts.                                                                                                                                                                                                   |
| `»»» context_file_directory`       | string                                                                           | false    |              | Context file directory is the working directory of the workspace agent. Internal only: same purpose as ContextFileOS.                                                                                                                                                                                                                                                                                      |
| `»»» context_file_os`              | string                                                                           | false    |              | Context file os is the operating system of the workspace agent. Internal only: used during prompt expansion so the LLM knows the OS even on turns where InsertSystem is not called.                                                                                                                                                                                                                        |
| `»»» context_file_path`            | string                                                                           | false    |              | Context file path is the absolute path of a file loaded into the LLM context (e.g. an AGENTS.md instruction file).                                                                                                                                                                                                                                                                                         |
| `»»» context_file_skill_meta_file` | string                                                                           | false    |              | Context file skill meta file is the basename of the skill meta file (e.g. "SKILL.md") at the time of persistence. Internal only: restored on subsequent turns so the read_skill tool uses the correct filename even when the agent configured a non-default value.                                                                                                                                         |
| `»»» context_file_truncated`       | boolean                                                                          | false    |              | Context file truncated indicates the file exceeded the 64KiB instruction file limit and was truncated.                                                                                                                                                                                                                                                                                                     |
| `»»» created_at`                   | string(date-time)                                                                | false    |              | Created at is the timestamp this part carries. The semantics depend on the part type: for tool-call and tool-result parts it is the time the call was emitted or the result was produced (tool duration is the result's created_at minus the call's created_at); for reasoning parts it is the time reasoning started streaming.                                                                           |
| `»»» data`                         | array                                                                            | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» end_line`                     | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» file_id`                      | string(uuid)                                                                     | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» file_name`                    | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» hook_rewritten`               | boolean                                                                          | false    |              | Hook rewritten indicates that a lifecycle hook replaced model-proposed tool input.                                                                                                                                                                                                                                                                                                                         |
| `»»» is_error`                     | boolean                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» is_media`                     | boolean                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» mcp_server_config_id`         | string(uuid)                                                                     | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» media_type`                   | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» name`                         | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» parsed_commands`              | array                                                                            | false    |              | Parsed commands holds parsed programs from an execute tool call's shell command, one entry per simple command in source order. Each entry is [program] or [program, arg] where arg is the first non-flag positional argument. Program names are normalized to their base name (e.g. /usr/bin/go becomes go). Only populated when ToolName is "execute" and the command parses successfully; nil otherwise. |
| `»»» provider_executed`            | boolean                                                                          | false    |              | Provider executed indicates the tool call was executed by the provider (e.g. Anthropic computer use).                                                                                                                                                                                                                                                                                                      |
| `»»» provider_metadata`            | array                                                                            | false    |              | Provider metadata holds provider-specific response metadata (e.g. Anthropic cache control hints) as raw JSON. Internal only: stripped by db2sdk before API responses.                                                                                                                                                                                                                                      |
| `»»» reasoning_delta`              | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» result`                       | array                                                                            | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» result_delta`                 | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» result_reset`                 | boolean                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» skill_description`            | string                                                                           | false    |              | Skill description is the short description from the skill's SKILL.md frontmatter.                                                                                                                                                                                                                                                                                                                          |
| `»»» skill_dir`                    | string                                                                           | false    |              | Skill dir is the absolute path to the skill directory inside the workspace filesystem. Internal only: used by read_skill/read_skill_file tools to locate skill files.                                                                                                                                                                                                                                      |
| `»»» skill_name`                   | string                                                                           | false    |              | Skill name is the kebab-case name of a discovered skill from the workspace's .agents/skills/ directory.                                                                                                                                                                                                                                                                                                    |
| `»»» source_id`                    | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» start_line`                   | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» text`                         | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» title`                        | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» tool_call_id`                 | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» tool_name`                    | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» type`                         | [codersdk.ChatMessagePartType](schemas.md#codersdkchatmessageparttype)           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» url`                          | string                                                                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» workspace_file_media_type`    | string                                                                           | false    |              | Workspace file media type is the best-effort declared MIME type.                                                                                                                                                                                                                                                                                                                                           |
| `»»» workspace_file_name`          | string                                                                           | false    |              | Workspace file name is the sanitized basename of a workspace upload.                                                                                                                                                                                                                                                                                                                                       |
| `»»» workspace_file_path`          | string                                                                           | false    |              | Workspace file path is the absolute path of a workspace upload. The bytes live on the workspace filesystem; only metadata is persisted on the message.                                                                                                                                                                                                                                                     |
| `»»» workspace_file_size`          | integer                                                                          | false    |              | Workspace file size is the byte size of a workspace upload.                                                                                                                                                                                                                                                                                                                                                |
| `»»» workspace_file_workspace_id`  | string(uuid)                                                                     | false    |              | Workspace file workspace ID identifies the workspace whose filesystem holds the uploaded bytes. References are only readable while the chat stays bound to that workspace.                                                                                                                                                                                                                                 |
| `»» created_at`                    | string(date-time)                                                                | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» created_by`                    | string(uuid)                                                                     | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» id`                            | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» model_config_id`               | string(uuid)                                                                     | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» queued_message_id`             | integer                                                                          | false    |              | Queued message ID is the ID of the queued message this message was promoted from. It matches ChatQueuedMessage.ID in the response that queued the message. It is nil when the message was not promoted from the queue (edits create a new message without it) or when a server version that did not record the link created it.                                                                            |
| `»» role`                          | [codersdk.ChatMessageRole](schemas.md#codersdkchatmessagerole)                   | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» usage`                         | [codersdk.ChatMessageUsage](schemas.md#codersdkchatmessageusage)                 | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» cache_creation_tokens`        | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» cache_read_tokens`            | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» context_limit`                | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» input_tokens`                 | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» output_tokens`                | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» reasoning_tokens`             | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»»» total_tokens`                 | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `» message_part`                   | [codersdk.ChatStreamMessagePart](schemas.md#codersdkchatstreammessagepart)       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» generation_attempt`            | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» history_version`               | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» part`                          | [codersdk.ChatMessagePart](schemas.md#codersdkchatmessagepart)                   | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» role`                          | [codersdk.ChatMessageRole](schemas.md#codersdkchatmessagerole)                   | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» seq`                           | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `» queued_messages`                | array                                                                            | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» chat_id`                       | string(uuid)                                                                     | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» content`                       | array                                                                            | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» created_at`                    | string(date-time)                                                                | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» id`                            | integer                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» model_config_id`               | string(uuid)                                                                     | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `» retry`                          | [codersdk.ChatStreamRetry](schemas.md#codersdkchatstreamretry)                   | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» attempt`                       | integer                                                                          | false    |              | Attempt is the 1-indexed retry attempt number.                                                                                                                                                                                                                                                                                                                                                             |
| `»» delay_ms`                      | integer                                                                          | false    |              | Delay ms is the backoff delay in milliseconds before the retry.                                                                                                                                                                                                                                                                                                                                            |
| `»» error`                         | string                                                                           | false    |              | Error is the normalized error message from the failed attempt.                                                                                                                                                                                                                                                                                                                                             |
| `»» kind`                          | [codersdk.ChatErrorKind](schemas.md#codersdkchaterrorkind)                       | false    |              | Kind classifies the retry reason for consistent client rendering.                                                                                                                                                                                                                                                                                                                                          |
| `»» provider`                      | string                                                                           | false    |              | Provider identifies the upstream model provider when known.                                                                                                                                                                                                                                                                                                                                                |
| `»» retrying_at`                   | string(date-time)                                                                | false    |              | Retrying at is the timestamp when the retry will be attempted.                                                                                                                                                                                                                                                                                                                                             |
| `»» status_code`                   | integer                                                                          | false    |              | Status code is the best-effort upstream HTTP status code.                                                                                                                                                                                                                                                                                                                                                  |
| `» status`                         | [codersdk.ChatStreamStatus](schemas.md#codersdkchatstreamstatus)                 | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `»» status`                        | [codersdk.ChatStatus](schemas.md#codersdkchatstatus)                             | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `» type`                           | [codersdk.ChatStreamEventType](schemas.md#codersdkchatstreameventtype)           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |

#### Enumerated Values

| Property | Value(s)                                                                                                                                                                                                                                                                                            |
|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `kind`   | `auth`, `config`, `content_filter`, `generic`, `hook_denied`, `hook_dispatch_failed`, `missing_key`, `overloaded`, `provider_disabled`, `rate_limit`, `stream_silence_timeout`, `timeout`, `usage_limit`                                                                                            |
| `type`   | `action_required`, `context-file`, `error`, `file`, `file-reference`, `history_reset`, `hook-context`, `hook-notice`, `message`, `message_part`, `preview_reset`, `queue_update`, `reasoning`, `retry`, `skill`, `source`, `status`, `text`, `tool-call`, `tool-result`, `workspace-file-reference` |
| `role`   | `assistant`, `system`, `tool`, `user`                                                                                                                                                                                                                                                               |
| `status` | `error`, `interrupting`, `requires_action`, `running`, `waiting`                                                                                                                                                                                                                                    |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Watch chat workspace git state via WebSockets

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/chats/{chat}/stream/git \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/chats/{chat}/stream/git`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Example responses

> 200 Response

```json
{
  "message": "string",
  "repositories": [
    {
      "branch": "string",
      "remote_origin": "string",
      "removed": true,
      "repo_root": "string",
      "unified_diff": "string"
    }
  ],
  "scanned_at": "2019-08-24T14:15:22Z",
  "type": "changes"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceAgentGitServerMessage](schemas.md#codersdkworkspaceagentgitservermessage) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Propose chat title

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats/{chat}/title/propose \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/chats/{chat}/title/propose`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `chat` | path | string(uuid) | true     | Chat ID     |

### Example responses

> 200 Response

```json
{
  "title": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ProposeChatTitleResponse](schemas.md#codersdkproposechattitleresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Submit chat tool results

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats/{chat}/tool-results \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/chats/{chat}/tool-results`

> Body parameter

```json
{
  "results": [
    {
      "is_error": true,
      "output": [
        0
      ],
      "tool_call_id": "string"
    }
  ]
}
```

### Parameters

| Name   | In   | Type                                                                             | Required | Description  |
|--------|------|----------------------------------------------------------------------------------|----------|--------------|
| `chat` | path | string(uuid)                                                                     | true     | Chat ID      |
| `body` | body | [codersdk.SubmitToolResultsRequest](schemas.md#codersdksubmittoolresultsrequest) | true     | Request body |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Upload a file to a chat's workspace

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/chats/{chat}/workspace-files \
  -H 'Content-Type: */*' \
  -H 'Accept: application/json' \
  -H 'Content-Disposition: string' \
  -H 'Coder-Session-Token: API_KEY' \
  --data-binary '@archive.zip'
```

`POST /api/v2/chats/{chat}/workspace-files`

Streams the request body into the chat workspace's
upload directory. The request Content-Type header is
recorded as the file's media type. There is no
server-imposed size cap; client cancellation aborts the
stream and the agent leaves no partial target file behind.

### Parameters

| Name                  | In     | Type         | Required | Description                                     |
|-----------------------|--------|--------------|----------|-------------------------------------------------|
| `chat`                | path   | string(uuid) | true     | Chat ID                                         |
| `Content-Disposition` | header | string       | true     | Filename of the file (attachment; filename=...) |
| `body`                | body   | string       | true     | Raw file binary data                            |

### Example responses

> 201 Response

```json
{
  "media_type": "string",
  "name": "string",
  "path": "string",
  "size": 0,
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                                    | Description           | Schema                                                                                         |
|--------|----------------------------------------------------------------------------|-----------------------|------------------------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)               | Created               | [codersdk.UploadChatWorkspaceFileResponse](schemas.md#codersdkuploadchatworkspacefileresponse) |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | Bad Request           | [codersdk.Response](schemas.md#codersdkresponse)                                               |
| 403    | [Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)             | Forbidden             | [codersdk.Response](schemas.md#codersdkresponse)                                               |
| 409    | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)              | Conflict              | [codersdk.Response](schemas.md#codersdkresponse)                                               |
| 429    | [Too Many Requests](https://tools.ietf.org/html/rfc6585#section-4)         | Too Many Requests     | [codersdk.Response](schemas.md#codersdkresponse)                                               |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal Server Error | [codersdk.Response](schemas.md#codersdkresponse)                                               |
| 502    | [Bad Gateway](https://tools.ietf.org/html/rfc7231#section-6.6.3)           | Bad Gateway           | [codersdk.Response](schemas.md#codersdkresponse)                                               |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List AI models and provider descriptors in an organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/chats/models \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/chats/models`

### Parameters

| Name           | In   | Type   | Required | Description             |
|----------------|------|--------|----------|-------------------------|
| `organization` | path | string | true     | Organization name or ID |

### Example responses

> 200 Response

```json
{
  "models": [
    {
      "ai_provider_id": "5a3b8ff9-20e7-4c37-ba1a-5b433e355819",
      "compression_threshold": 0,
      "context_limit": 0,
      "created_at": "2019-08-24T14:15:22Z",
      "display_name": "string",
      "enabled": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_default": true,
      "model": "string",
      "model_config": {
        "frequency_penalty": 0,
        "max_output_tokens": 0,
        "openai_config": {
          "reasoning_model": true,
          "use_responses_api": true
        },
        "presence_penalty": 0,
        "provider_options": {
          "anthropic": {
            "allowed_domains": [
              "string"
            ],
            "blocked_domains": [
              "string"
            ],
            "context_1m_enabled": true,
            "disable_parallel_tool_use": true,
            "send_reasoning": true,
            "thinking": {
              "budget_tokens": 0
            },
            "thinking_display": "string",
            "web_search_enabled": true
          },
          "google": {
            "cached_content": "string",
            "safety_settings": [
              {
                "category": "string",
                "threshold": "string"
              }
            ],
            "thinking_config": {
              "include_thoughts": true,
              "thinking_budget": 0,
              "thinking_level": "string"
            },
            "threshold": "string",
            "web_search_enabled": true
          },
          "openai": {
            "allowed_domains": [
              "string"
            ],
            "include": [
              "string"
            ],
            "instructions": "string",
            "log_probs": true,
            "logit_bias": {
              "property1": 0,
              "property2": 0
            },
            "max_completion_tokens": 0,
            "max_tool_calls": 0,
            "metadata": {
              "property1": null,
              "property2": null
            },
            "parallel_tool_calls": true,
            "prediction": {
              "property1": null,
              "property2": null
            },
            "prompt_cache_key": "string",
            "reasoning_mode": "string",
            "reasoning_summary": "string",
            "safety_identifier": "string",
            "search_context_size": "string",
            "service_tier": "string",
            "store": true,
            "strict_json_schema": true,
            "structured_outputs": true,
            "text_verbosity": "string",
            "top_log_probs": 0,
            "user": "string",
            "web_search_enabled": true
          },
          "openaicompat": {
            "user": "string"
          },
          "openrouter": {
            "extra_body": {
              "property1": null,
              "property2": null
            },
            "include_usage": true,
            "log_probs": true,
            "logit_bias": {
              "property1": 0,
              "property2": 0
            },
            "parallel_tool_calls": true,
            "provider": {
              "allow_fallbacks": true,
              "data_collection": "string",
              "ignore": [
                "string"
              ],
              "only": [
                "string"
              ],
              "order": [
                "string"
              ],
              "quantizations": [
                "string"
              ],
              "require_parameters": true,
              "sort": "string"
            },
            "reasoning": {
              "enabled": true,
              "exclude": true,
              "max_tokens": 0
            },
            "user": "string"
          },
          "vercel": {
            "extra_body": {
              "property1": null,
              "property2": null
            },
            "logit_bias": {
              "property1": 0,
              "property2": 0
            },
            "logprobs": true,
            "parallel_tool_calls": true,
            "providerOptions": {
              "models": [
                "string"
              ],
              "order": [
                "string"
              ]
            },
            "reasoning": {
              "enabled": true,
              "exclude": true,
              "max_tokens": 0
            },
            "top_logprobs": 0,
            "user": "string"
          }
        },
        "reasoning_effort": {
          "default": "string",
          "max": "string"
        },
        "temperature": 0,
        "top_k": 0,
        "top_p": 0
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "reasoning_efforts": [
        "string"
      ],
      "updated_at": "2019-08-24T14:15:22Z"
    }
  ],
  "providers": [
    {
      "allow_user_api_key": true,
      "available": true,
      "display_name": "string",
      "enabled": true,
      "has_api_key": true,
      "has_effective_api_key": true,
      "has_user_api_key": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "type": "string",
      "unavailable_reason": "missing_api_key"
    }
  ],
  "unsupported_providers": [
    {
      "display_name": "string",
      "provider": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationChatModelsResponse](schemas.md#codersdkorganizationchatmodelsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create an AI model in an organization

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/chats/models \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations/{organization}/chats/models`

> Body parameter

```json
{
  "ai_provider_id": "5a3b8ff9-20e7-4c37-ba1a-5b433e355819",
  "compression_threshold": 0,
  "context_limit": 0,
  "display_name": "string",
  "enabled": true,
  "is_default": true,
  "model": "string",
  "model_config": {
    "frequency_penalty": 0,
    "max_output_tokens": 0,
    "openai_config": {
      "reasoning_model": true,
      "use_responses_api": true
    },
    "presence_penalty": 0,
    "provider_options": {
      "anthropic": {
        "allowed_domains": [
          "string"
        ],
        "blocked_domains": [
          "string"
        ],
        "context_1m_enabled": true,
        "disable_parallel_tool_use": true,
        "send_reasoning": true,
        "thinking": {
          "budget_tokens": 0
        },
        "thinking_display": "string",
        "web_search_enabled": true
      },
      "google": {
        "cached_content": "string",
        "safety_settings": [
          {
            "category": "string",
            "threshold": "string"
          }
        ],
        "thinking_config": {
          "include_thoughts": true,
          "thinking_budget": 0,
          "thinking_level": "string"
        },
        "threshold": "string",
        "web_search_enabled": true
      },
      "openai": {
        "allowed_domains": [
          "string"
        ],
        "include": [
          "string"
        ],
        "instructions": "string",
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "max_completion_tokens": 0,
        "max_tool_calls": 0,
        "metadata": {
          "property1": null,
          "property2": null
        },
        "parallel_tool_calls": true,
        "prediction": {
          "property1": null,
          "property2": null
        },
        "prompt_cache_key": "string",
        "reasoning_mode": "string",
        "reasoning_summary": "string",
        "safety_identifier": "string",
        "search_context_size": "string",
        "service_tier": "string",
        "store": true,
        "strict_json_schema": true,
        "structured_outputs": true,
        "text_verbosity": "string",
        "top_log_probs": 0,
        "user": "string",
        "web_search_enabled": true
      },
      "openaicompat": {
        "user": "string"
      },
      "openrouter": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "include_usage": true,
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "parallel_tool_calls": true,
        "provider": {
          "allow_fallbacks": true,
          "data_collection": "string",
          "ignore": [
            "string"
          ],
          "only": [
            "string"
          ],
          "order": [
            "string"
          ],
          "quantizations": [
            "string"
          ],
          "require_parameters": true,
          "sort": "string"
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "user": "string"
      },
      "vercel": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "logprobs": true,
        "parallel_tool_calls": true,
        "providerOptions": {
          "models": [
            "string"
          ],
          "order": [
            "string"
          ]
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "top_logprobs": 0,
        "user": "string"
      }
    },
    "reasoning_effort": {
      "default": "string",
      "max": "string"
    },
    "temperature": 0,
    "top_k": 0,
    "top_p": 0
  }
}
```

### Parameters

| Name           | In   | Type                                                                         | Required | Description             |
|----------------|------|------------------------------------------------------------------------------|----------|-------------------------|
| `organization` | path | string                                                                       | true     | Organization name or ID |
| `body`         | body | [codersdk.CreateChatModelRequest](schemas.md#codersdkcreatechatmodelrequest) | true     | Model                   |

### Example responses

> 201 Response

```json
{
  "ai_provider_id": "5a3b8ff9-20e7-4c37-ba1a-5b433e355819",
  "compression_threshold": 0,
  "context_limit": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "display_name": "string",
  "enabled": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_default": true,
  "model": "string",
  "model_config": {
    "frequency_penalty": 0,
    "max_output_tokens": 0,
    "openai_config": {
      "reasoning_model": true,
      "use_responses_api": true
    },
    "presence_penalty": 0,
    "provider_options": {
      "anthropic": {
        "allowed_domains": [
          "string"
        ],
        "blocked_domains": [
          "string"
        ],
        "context_1m_enabled": true,
        "disable_parallel_tool_use": true,
        "send_reasoning": true,
        "thinking": {
          "budget_tokens": 0
        },
        "thinking_display": "string",
        "web_search_enabled": true
      },
      "google": {
        "cached_content": "string",
        "safety_settings": [
          {
            "category": "string",
            "threshold": "string"
          }
        ],
        "thinking_config": {
          "include_thoughts": true,
          "thinking_budget": 0,
          "thinking_level": "string"
        },
        "threshold": "string",
        "web_search_enabled": true
      },
      "openai": {
        "allowed_domains": [
          "string"
        ],
        "include": [
          "string"
        ],
        "instructions": "string",
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "max_completion_tokens": 0,
        "max_tool_calls": 0,
        "metadata": {
          "property1": null,
          "property2": null
        },
        "parallel_tool_calls": true,
        "prediction": {
          "property1": null,
          "property2": null
        },
        "prompt_cache_key": "string",
        "reasoning_mode": "string",
        "reasoning_summary": "string",
        "safety_identifier": "string",
        "search_context_size": "string",
        "service_tier": "string",
        "store": true,
        "strict_json_schema": true,
        "structured_outputs": true,
        "text_verbosity": "string",
        "top_log_probs": 0,
        "user": "string",
        "web_search_enabled": true
      },
      "openaicompat": {
        "user": "string"
      },
      "openrouter": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "include_usage": true,
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "parallel_tool_calls": true,
        "provider": {
          "allow_fallbacks": true,
          "data_collection": "string",
          "ignore": [
            "string"
          ],
          "only": [
            "string"
          ],
          "order": [
            "string"
          ],
          "quantizations": [
            "string"
          ],
          "require_parameters": true,
          "sort": "string"
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "user": "string"
      },
      "vercel": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "logprobs": true,
        "parallel_tool_calls": true,
        "providerOptions": {
          "models": [
            "string"
          ],
          "order": [
            "string"
          ]
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "top_logprobs": 0,
        "user": "string"
      }
    },
    "reasoning_effort": {
      "default": "string",
      "max": "string"
    },
    "temperature": 0,
    "top_k": 0,
    "top_p": 0
  },
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "reasoning_efforts": [
    "string"
  ],
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                             |
|--------|--------------------------------------------------------------|-------------|----------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.ChatModel](schemas.md#codersdkchatmodel) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List user AI provider key configurations

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/ai-provider-keys \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/ai-provider-keys`

### Parameters

| Name   | In   | Type   | Required | Description              |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true     | User ID, username, or me |

### Example responses

> 200 Response

```json
[
  {
    "byok_enabled": true,
    "has_provider_api_key": true,
    "has_user_api_key": true,
    "provider": {
      "deleted": true,
      "display_name": "string",
      "enabled": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "type": "openai"
    }
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                  |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.UserAIProviderKeyConfig](schemas.md#codersdkuseraiproviderkeyconfig) |

<h3 id="list-user-ai-provider-key-configurations-responseschema">Response Schema</h3>

Status Code **200**

| Name                     | Type                                                               | Required | Restrictions | Description |
|--------------------------|--------------------------------------------------------------------|----------|--------------|-------------|
| `[array item]`           | array                                                              | false    |              |             |
| `» byok_enabled`         | boolean                                                            | false    |              |             |
| `» has_provider_api_key` | boolean                                                            | false    |              |             |
| `» has_user_api_key`     | boolean                                                            | false    |              |             |
| `» provider`             | [codersdk.AIProviderSummary](schemas.md#codersdkaiprovidersummary) | false    |              |             |
| `»» deleted`             | boolean                                                            | false    |              |             |
| `»» display_name`        | string                                                             | false    |              |             |
| `»» enabled`             | boolean                                                            | false    |              |             |
| `»» icon`                | string                                                             | false    |              |             |
| `»» id`                  | string(uuid)                                                       | false    |              |             |
| `»» name`                | string                                                             | false    |              |             |
| `»» type`                | [codersdk.AIProviderType](schemas.md#codersdkaiprovidertype)       | false    |              |             |

#### Enumerated Values

| Property | Value(s)                                                                                                |
|----------|---------------------------------------------------------------------------------------------------------|
| `type`   | `anthropic`, `azure`, `bedrock`, `copilot`, `google`, `openai`, `openai-compat`, `openrouter`, `vercel` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user AI provider key

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/ai-provider-keys/{aiProvider} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/ai-provider-keys/{aiProvider}`

> Body parameter

```json
{
  "api_key": "string"
}
```

### Parameters

| Name         | In   | Type                                                                                         | Required | Description              |
|--------------|------|----------------------------------------------------------------------------------------------|----------|--------------------------|
| `user`       | path | string                                                                                       | true     | User ID, username, or me |
| `aiProvider` | path | string(uuid)                                                                                 | true     | AI provider ID           |
| `body`       | body | [codersdk.CreateUserAIProviderKeyRequest](schemas.md#codersdkcreateuseraiproviderkeyrequest) | true     | Request body             |

### Example responses

> 200 Response

```json
{
  "byok_enabled": true,
  "has_provider_api_key": true,
  "has_user_api_key": true,
  "provider": {
    "deleted": true,
    "display_name": "string",
    "enabled": true,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "type": "openai"
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                         |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserAIProviderKeyConfig](schemas.md#codersdkuseraiproviderkeyconfig) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete user AI provider key

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/users/{user}/ai-provider-keys/{aiProvider} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/users/{user}/ai-provider-keys/{aiProvider}`

### Parameters

| Name         | In   | Type         | Required | Description              |
|--------------|------|--------------|----------|--------------------------|
| `user`       | path | string       | true     | User ID, username, or me |
| `aiProvider` | path | string(uuid) | true     | AI provider ID           |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Debug

Source: https://coder.com/docs/reference/api/debug

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Debug Info Wireguard Coordinator

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/debug/coordinator \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/debug/coordinator`

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Debug Info Deployment Health

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/debug/health \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/debug/health`

### Parameters

| Name    | In    | Type    | Required | Description                |
|---------|-------|---------|----------|----------------------------|
| `force` | query | boolean | false    | Force a healthcheck to run |

### Example responses

> 200 Response

```json
{
  "access_url": {
    "access_url": "string",
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "healthz_response": "string",
    "reachable": true,
    "severity": "ok",
    "status_code": 0,
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "coder_version": "string",
  "database": {
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "latency": "string",
    "latency_ms": 0,
    "reachable": true,
    "severity": "ok",
    "threshold_ms": 0,
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "derp": {
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "netcheck": {
      "captivePortal": "string",
      "globalV4": "string",
      "globalV6": "string",
      "icmpv4": true,
      "ipv4": true,
      "ipv4CanSend": true,
      "ipv6": true,
      "ipv6CanSend": true,
      "mappingVariesByDestIP": "string",
      "oshasIPv6": true,
      "pcp": "string",
      "pmp": "string",
      "preferredDERP": 0,
      "regionLatency": {
        "property1": 0,
        "property2": 0
      },
      "regionV4Latency": {
        "property1": 0,
        "property2": 0
      },
      "regionV6Latency": {
        "property1": 0,
        "property2": 0
      },
      "udp": true,
      "upnP": "string"
    },
    "netcheck_err": "string",
    "netcheck_logs": [
      "string"
    ],
    "regions": {
      "property1": {
        "error": "string",
        "healthy": true,
        "node_reports": [
          {
            "can_exchange_messages": true,
            "client_errs": [
              [
                "string"
              ]
            ],
            "client_logs": [
              [
                "string"
              ]
            ],
            "error": "string",
            "healthy": true,
            "node": {
              "canPort80": true,
              "certName": "string",
              "derpport": 0,
              "forceHTTP": true,
              "hostName": "string",
              "insecureForTests": true,
              "ipv4": "string",
              "ipv6": "string",
              "name": "string",
              "regionID": 0,
              "stunonly": true,
              "stunport": 0,
              "stuntestIP": "string"
            },
            "node_info": {
              "tokenBucketBytesBurst": 0,
              "tokenBucketBytesPerSecond": 0
            },
            "round_trip_ping": "string",
            "round_trip_ping_ms": 0,
            "severity": "ok",
            "stun": {
              "canSTUN": true,
              "enabled": true,
              "error": "string"
            },
            "uses_websocket": true,
            "warnings": [
              {
                "code": "EUNKNOWN",
                "message": "string"
              }
            ]
          }
        ],
        "region": {
          "avoid": true,
          "embeddedRelay": true,
          "nodes": [
            {
              "canPort80": true,
              "certName": "string",
              "derpport": 0,
              "forceHTTP": true,
              "hostName": "string",
              "insecureForTests": true,
              "ipv4": "string",
              "ipv6": "string",
              "name": "string",
              "regionID": 0,
              "stunonly": true,
              "stunport": 0,
              "stuntestIP": "string"
            }
          ],
          "regionCode": "string",
          "regionID": 0,
          "regionName": "string"
        },
        "severity": "ok",
        "warnings": [
          {
            "code": "EUNKNOWN",
            "message": "string"
          }
        ]
      },
      "property2": {
        "error": "string",
        "healthy": true,
        "node_reports": [
          {
            "can_exchange_messages": true,
            "client_errs": [
              [
                "string"
              ]
            ],
            "client_logs": [
              [
                "string"
              ]
            ],
            "error": "string",
            "healthy": true,
            "node": {
              "canPort80": true,
              "certName": "string",
              "derpport": 0,
              "forceHTTP": true,
              "hostName": "string",
              "insecureForTests": true,
              "ipv4": "string",
              "ipv6": "string",
              "name": "string",
              "regionID": 0,
              "stunonly": true,
              "stunport": 0,
              "stuntestIP": "string"
            },
            "node_info": {
              "tokenBucketBytesBurst": 0,
              "tokenBucketBytesPerSecond": 0
            },
            "round_trip_ping": "string",
            "round_trip_ping_ms": 0,
            "severity": "ok",
            "stun": {
              "canSTUN": true,
              "enabled": true,
              "error": "string"
            },
            "uses_websocket": true,
            "warnings": [
              {
                "code": "EUNKNOWN",
                "message": "string"
              }
            ]
          }
        ],
        "region": {
          "avoid": true,
          "embeddedRelay": true,
          "nodes": [
            {
              "canPort80": true,
              "certName": "string",
              "derpport": 0,
              "forceHTTP": true,
              "hostName": "string",
              "insecureForTests": true,
              "ipv4": "string",
              "ipv6": "string",
              "name": "string",
              "regionID": 0,
              "stunonly": true,
              "stunport": 0,
              "stuntestIP": "string"
            }
          ],
          "regionCode": "string",
          "regionID": 0,
          "regionName": "string"
        },
        "severity": "ok",
        "warnings": [
          {
            "code": "EUNKNOWN",
            "message": "string"
          }
        ]
      }
    },
    "severity": "ok",
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "healthy": true,
  "provisioner_daemons": {
    "dismissed": true,
    "error": "string",
    "items": [
      {
        "provisioner_daemon": {
          "api_version": "string",
          "created_at": "2019-08-24T14:15:22Z",
          "current_job": {
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "status": "pending",
            "template_display_name": "string",
            "template_icon": "string",
            "template_name": "string"
          },
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
          "key_name": "string",
          "last_seen_at": "2019-08-24T14:15:22Z",
          "name": "string",
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "previous_job": {
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "status": "pending",
            "template_display_name": "string",
            "template_icon": "string",
            "template_name": "string"
          },
          "provisioners": [
            "string"
          ],
          "status": "offline",
          "tags": {
            "property1": "string",
            "property2": "string"
          },
          "version": "string"
        },
        "warnings": [
          {
            "code": "EUNKNOWN",
            "message": "string"
          }
        ]
      }
    ],
    "severity": "ok",
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "severity": "ok",
  "time": "2019-08-24T14:15:22Z",
  "websocket": {
    "body": "string",
    "code": 0,
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "severity": "ok",
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "workspace_proxy": {
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "severity": "ok",
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ],
    "workspace_proxies": {
      "regions": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "deleted": true,
          "derp_enabled": true,
          "derp_only": true,
          "display_name": "string",
          "healthy": true,
          "icon_url": "string",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "name": "string",
          "path_app_url": "string",
          "status": {
            "checked_at": "2019-08-24T14:15:22Z",
            "report": {
              "errors": [
                "string"
              ],
              "warnings": [
                "string"
              ]
            },
            "status": "ok"
          },
          "updated_at": "2019-08-24T14:15:22Z",
          "version": "string",
          "wildcard_hostname": "string"
        }
      ]
    }
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                               |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [healthsdk.HealthcheckReport](schemas.md#healthsdkhealthcheckreport) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get health settings

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/debug/health/settings \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/debug/health/settings`

### Example responses

> 200 Response

```json
{
  "dismissed_healthchecks": [
    "DERP"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                         |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [healthsdk.HealthSettings](schemas.md#healthsdkhealthsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update health settings

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/debug/health/settings \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/debug/health/settings`

> Body parameter

```json
{
  "dismissed_healthchecks": [
    "DERP"
  ]
}
```

### Parameters

| Name   | In   | Type                                                                       | Required | Description            |
|--------|------|----------------------------------------------------------------------------|----------|------------------------|
| `body` | body | [healthsdk.UpdateHealthSettings](schemas.md#healthsdkupdatehealthsettings) | true     | Update health settings |

### Example responses

> 200 Response

```json
{
  "dismissed_healthchecks": [
    "DERP"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                     |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [healthsdk.UpdateHealthSettings](schemas.md#healthsdkupdatehealthsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Debug Info Tailnet

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/debug/tailnet \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/debug/tailnet`

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Enterprise

Source: https://coder.com/docs/reference/api/enterprise

<!-- DO NOT EDIT | GENERATED CONTENT -->

## OAuth2 authorization server metadata

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/.well-known/oauth-authorization-server \
  -H 'Accept: application/json'
```

`GET /.well-known/oauth-authorization-server`

### Example responses

> 200 Response

```json
{
  "authorization_endpoint": "string",
  "code_challenge_methods_supported": [
    "S256"
  ],
  "grant_types_supported": [
    "authorization_code"
  ],
  "issuer": "string",
  "registration_endpoint": "string",
  "response_types_supported": [
    "code"
  ],
  "revocation_endpoint": "string",
  "scopes_supported": [
    "string"
  ],
  "token_endpoint": "string",
  "token_endpoint_auth_methods_supported": [
    "client_secret_basic"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                             |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OAuth2AuthorizationServerMetadata](schemas.md#codersdkoauth2authorizationservermetadata) |

## OAuth2 protected resource metadata

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/.well-known/oauth-protected-resource \
  -H 'Accept: application/json'
```

`GET /.well-known/oauth-protected-resource`

### Example responses

> 200 Response

```json
{
  "authorization_servers": [
    "string"
  ],
  "bearer_methods_supported": [
    "string"
  ],
  "resource": "string",
  "scopes_supported": [
    "string"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                         |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OAuth2ProtectedResourceMetadata](schemas.md#codersdkoauth2protectedresourcemetadata) |

## Get agent firewall session by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/agent-firewall/sessions/{id} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/agent-firewall/sessions/{id}`

### Parameters

| Name | In   | Type         | Required | Description               |
|------|------|--------------|----------|---------------------------|
| `id` | path | string(uuid) | true     | Agent firewall session ID |

### Example responses

> 200 Response

```json
{
  "confined_process": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "started_at": "2019-08-24T14:15:22Z",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AgentFirewallSession](schemas.md#codersdkagentfirewallsession) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get agent firewall session logs

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/agent-firewall/sessions/{id}/logs \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/agent-firewall/sessions/{id}/logs`

### Parameters

| Name         | In    | Type         | Required | Description                                    |
|--------------|-------|--------------|----------|------------------------------------------------|
| `id`         | path  | string(uuid) | true     | Agent firewall session ID                      |
| `seq_after`  | query | integer      | false    | Inclusive lower bound on sequence number       |
| `seq_before` | query | integer      | false    | Exclusive upper bound on sequence number       |
| `limit`      | query | integer      | false    | Maximum number of logs to return (default 100) |

### Example responses

> 200 Response

```json
{
  "results": [
    {
      "allowed": true,
      "captured_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "detail": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "matched_rule": "string",
      "method": "string",
      "proto": "string",
      "sequence_number": 0,
      "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AgentFirewallSessionLogsResponse](schemas.md#codersdkagentfirewallsessionlogsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List AI Gateway keys

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai-gateway/keys \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/ai-gateway/keys`

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "key_prefix": "string",
    "last_heartbeat_at": "2019-08-24T14:15:22Z",
    "name": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                            |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.AIGatewayKey](schemas.md#codersdkaigatewaykey) |

<h3 id="list-ai-gateway-keys-responseschema">Response Schema</h3>

Status Code **200**

| Name                  | Type              | Required | Restrictions | Description |
|-----------------------|-------------------|----------|--------------|-------------|
| `[array item]`        | array             | false    |              |             |
| `» created_at`        | string(date-time) | false    |              |             |
| `» id`                | string(uuid)      | false    |              |             |
| `» key_prefix`        | string            | false    |              |             |
| `» last_heartbeat_at` | string(date-time) | false    |              |             |
| `» name`              | string            | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create AI Gateway key

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/ai-gateway/keys \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/ai-gateway/keys`

> Body parameter

```json
{
  "name": "string"
}
```

### Parameters

| Name   | In   | Type                                                                               | Required | Description                   |
|--------|------|------------------------------------------------------------------------------------|----------|-------------------------------|
| `body` | body | [codersdk.CreateAIGatewayKeyRequest](schemas.md#codersdkcreateaigatewaykeyrequest) | true     | Create AI Gateway key request |

### Example responses

> 201 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "key": "string",
  "key_prefix": "string",
  "name": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                                               |
|--------|--------------------------------------------------------------|-------------|--------------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.CreateAIGatewayKeyResponse](schemas.md#codersdkcreateaigatewaykeyresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete AI Gateway key

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/ai-gateway/keys/{key} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/ai-gateway/keys/{key}`

### Parameters

| Name  | In   | Type         | Required | Description |
|-------|------|--------------|----------|-------------|
| `key` | path | string(uuid) | true     | Key ID      |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## AI Gateway serve

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/ai-gateway/serve \
  -H 'X-AI-Governance-Gateway-Key: API_KEY'
```

`GET /api/v2/ai-gateway/serve`

### Responses

| Status | Meaning                                                                  | Description         | Schema |
|--------|--------------------------------------------------------------------------|---------------------|--------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get appearance

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/appearance \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/appearance`

### Example responses

> 200 Response

```json
{
  "announcement_banners": [
    {
      "background_color": "string",
      "enabled": true,
      "message": "string"
    }
  ],
  "application_name": "string",
  "codernauts_enabled": true,
  "docs_url": "string",
  "logo_url": "string",
  "service_banner": {
    "background_color": "string",
    "enabled": true,
    "message": "string"
  },
  "support_links": [
    {
      "icon": "bug",
      "location": "navbar",
      "name": "string",
      "target": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AppearanceConfig](schemas.md#codersdkappearanceconfig) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update appearance

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/appearance \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/appearance`

> Body parameter

```json
{
  "announcement_banners": [
    {
      "background_color": "string",
      "enabled": true,
      "message": "string"
    }
  ],
  "application_name": "string",
  "codernauts_enabled": true,
  "logo_url": "string",
  "service_banner": {
    "background_color": "string",
    "enabled": true,
    "message": "string"
  }
}
```

### Parameters

| Name   | In   | Type                                                                         | Required | Description               |
|--------|------|------------------------------------------------------------------------------|----------|---------------------------|
| `body` | body | [codersdk.UpdateAppearanceConfig](schemas.md#codersdkupdateappearanceconfig) | true     | Update appearance request |

### Example responses

> 200 Response

```json
{
  "announcement_banners": [
    {
      "background_color": "string",
      "enabled": true,
      "message": "string"
    }
  ],
  "application_name": "string",
  "codernauts_enabled": true,
  "logo_url": "string",
  "service_banner": {
    "background_color": "string",
    "enabled": true,
    "message": "string"
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                       |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UpdateAppearanceConfig](schemas.md#codersdkupdateappearanceconfig) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get connection logs

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/connectionlog?limit=0 \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/connectionlog`

### Parameters

| Name     | In    | Type    | Required | Description  |
|----------|-------|---------|----------|--------------|
| `q`      | query | string  | false    | Search query |
| `limit`  | query | integer | true     | Page limit   |
| `offset` | query | integer | false    | Page offset  |

### Example responses

> 200 Response

```json
{
  "connection_logs": [
    {
      "agent_name": "string",
      "connect_time": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "ip": "string",
      "organization": {
        "display_name": "string",
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string"
      },
      "ssh_info": {
        "connection_id": "d3547de1-d1f2-4344-b4c2-17169b7526f9",
        "disconnect_reason": "string",
        "disconnect_time": "2019-08-24T14:15:22Z",
        "exit_code": 0
      },
      "type": "ssh",
      "web_info": {
        "slug_or_port": "string",
        "status_code": 0,
        "user": {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "has_ai_seat": true,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "organization_ids": [
            "497f6eca-6276-4993-bfeb-53cbbbba6f08"
          ],
          "roles": [
            {
              "display_name": "string",
              "name": "string",
              "organization_id": "string"
            }
          ],
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        },
        "user_agent": "string"
      },
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string",
      "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
      "workspace_owner_username": "string"
    }
  ],
  "count": 0,
  "count_cap": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                     |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ConnectionLogResponse](schemas.md#codersdkconnectionlogresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Report a premium paywall click

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/deployment/premium-funnel-events \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/deployment/premium-funnel-events`

> Body parameter

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "source": "aibridge_session_threads",
  "variant": "premium"
}
```

### Parameters

| Name   | In   | Type                                                                               | Required | Description          |
|--------|------|------------------------------------------------------------------------------------|----------|----------------------|
| `body` | body | [codersdk.PremiumFunnelEventRequest](schemas.md#codersdkpremiumfunneleventrequest) | true     | Premium funnel event |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get entitlements

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/entitlements \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/entitlements`

### Example responses

> 200 Response

```json
{
  "errors": [
    "string"
  ],
  "features": {
    "property1": {
      "actual": 0,
      "actual_ms": 0,
      "enabled": true,
      "entitlement": "entitled",
      "hard_limit": 0,
      "limit": 0,
      "soft_limit": 0,
      "usage_period": {
        "end": "2019-08-24T14:15:22Z",
        "issued_at": "2019-08-24T14:15:22Z",
        "start": "2019-08-24T14:15:22Z"
      }
    },
    "property2": {
      "actual": 0,
      "actual_ms": 0,
      "enabled": true,
      "entitlement": "entitled",
      "hard_limit": 0,
      "limit": 0,
      "soft_limit": 0,
      "usage_period": {
        "end": "2019-08-24T14:15:22Z",
        "issued_at": "2019-08-24T14:15:22Z",
        "start": "2019-08-24T14:15:22Z"
      }
    }
  },
  "has_license": true,
  "refreshed_at": "2019-08-24T14:15:22Z",
  "require_telemetry": true,
  "trial": true,
  "warnings": [
    "string"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Entitlements](schemas.md#codersdkentitlements) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get groups

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/groups?organization=string&has_member=string&group_ids=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/groups`

### Parameters

| Name           | In    | Type   | Required | Description                       |
|----------------|-------|--------|----------|-----------------------------------|
| `organization` | query | string | true     | Organization ID or name           |
| `has_member`   | query | string | true     | User ID or name                   |
| `group_ids`    | query | string | true     | Comma separated list of group IDs |

### Example responses

> 200 Response

```json
[
  {
    "avatar_url": "http://example.com",
    "display_name": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "members": [
      {
        "avatar_url": "http://example.com",
        "created_at": "2019-08-24T14:15:22Z",
        "email": "user@example.com",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "is_service_account": true,
        "last_seen_at": "2019-08-24T14:15:22Z",
        "login_type": "",
        "name": "string",
        "status": "active",
        "theme_preference": "string",
        "updated_at": "2019-08-24T14:15:22Z",
        "username": "string"
      }
    ],
    "name": "string",
    "organization_display_name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_name": "string",
    "quota_allowance": 0,
    "source": "user",
    "total_member_count": 0
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                              |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Group](schemas.md#codersdkgroup) |

<h3 id="get-groups-responseschema">Response Schema</h3>

Status Code **200**

| Name                          | Type                                                   | Required | Restrictions | Description                                                                                                                                                           |
|-------------------------------|--------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                | array                                                  | false    |              |                                                                                                                                                                       |
| `» avatar_url`                | string(uri)                                            | false    |              |                                                                                                                                                                       |
| `» display_name`              | string                                                 | false    |              |                                                                                                                                                                       |
| `» id`                        | string(uuid)                                           | false    |              |                                                                                                                                                                       |
| `» members`                   | array                                                  | false    |              |                                                                                                                                                                       |
| `»» avatar_url`               | string(uri)                                            | false    |              |                                                                                                                                                                       |
| `»» created_at`               | string(date-time)                                      | true     |              |                                                                                                                                                                       |
| `»» email`                    | string(email)                                          | true     |              |                                                                                                                                                                       |
| `»» id`                       | string(uuid)                                           | true     |              |                                                                                                                                                                       |
| `»» is_service_account`       | boolean                                                | false    |              |                                                                                                                                                                       |
| `»» last_seen_at`             | string(date-time)                                      | false    |              |                                                                                                                                                                       |
| `»» login_type`               | [codersdk.LoginType](schemas.md#codersdklogintype)     | false    |              |                                                                                                                                                                       |
| `»» name`                     | string                                                 | false    |              |                                                                                                                                                                       |
| `»» status`                   | [codersdk.UserStatus](schemas.md#codersdkuserstatus)   | false    |              |                                                                                                                                                                       |
| `»» theme_preference`         | string                                                 | false    |              | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead.                                                                            |
| `»» updated_at`               | string(date-time)                                      | false    |              |                                                                                                                                                                       |
| `»» username`                 | string                                                 | true     |              |                                                                                                                                                                       |
| `» name`                      | string                                                 | false    |              |                                                                                                                                                                       |
| `» organization_display_name` | string                                                 | false    |              |                                                                                                                                                                       |
| `» organization_id`           | string(uuid)                                           | false    |              |                                                                                                                                                                       |
| `» organization_name`         | string                                                 | false    |              |                                                                                                                                                                       |
| `» quota_allowance`           | integer                                                | false    |              |                                                                                                                                                                       |
| `» source`                    | [codersdk.GroupSource](schemas.md#codersdkgroupsource) | false    |              |                                                                                                                                                                       |
| `» total_member_count`        | integer                                                | false    |              | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. |

#### Enumerated Values

| Property     | Value(s)                                          |
|--------------|---------------------------------------------------|
| `login_type` | ``, `github`, `none`, `oidc`, `password`, `token` |
| `status`     | `active`, `suspended`                             |
| `source`     | `oidc`, `user`                                    |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/groups/{group} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/groups/{group}`

### Parameters

| Name              | In    | Type    | Required | Description                       |
|-------------------|-------|---------|----------|-----------------------------------|
| `group`           | path  | string  | true     | Group id                          |
| `exclude_members` | query | boolean | false    | Exclude members from the response |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "source": "user",
  "total_member_count": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                     |
|--------|---------------------------------------------------------|-------------|--------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Group](schemas.md#codersdkgroup) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete group by name

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/groups/{group} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/groups/{group}`

### Parameters

| Name    | In   | Type   | Required | Description |
|---------|------|--------|----------|-------------|
| `group` | path | string | true     | Group name  |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "source": "user",
  "total_member_count": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                     |
|--------|---------------------------------------------------------|-------------|--------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Group](schemas.md#codersdkgroup) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update group by name

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/groups/{group} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/groups/{group}`

> Body parameter

```json
{
  "add_users": [
    "string"
  ],
  "avatar_url": "string",
  "display_name": "string",
  "name": "string",
  "quota_allowance": 0,
  "remove_users": [
    "string"
  ]
}
```

### Parameters

| Name    | In   | Type                                                               | Required | Description         |
|---------|------|--------------------------------------------------------------------|----------|---------------------|
| `group` | path | string                                                             | true     | Group name          |
| `body`  | body | [codersdk.PatchGroupRequest](schemas.md#codersdkpatchgrouprequest) | true     | Patch group request |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "source": "user",
  "total_member_count": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                     |
|--------|---------------------------------------------------------|-------------|--------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Group](schemas.md#codersdkgroup) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group AI budget

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/groups/{group}/ai/budget \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/groups/{group}/ai/budget`

### Parameters

| Name    | In   | Type         | Required | Description |
|---------|------|--------------|----------|-------------|
| `group` | path | string(uuid) | true     | Group ID    |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                     |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupAIBudget](schemas.md#codersdkgroupaibudget) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Upsert group AI budget

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/groups/{group}/ai/budget \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/groups/{group}/ai/budget`

> Body parameter

```json
{
  "spend_limit_micros": 0
}
```

### Parameters

| Name    | In   | Type                                                                                 | Required | Description                    |
|---------|------|--------------------------------------------------------------------------------------|----------|--------------------------------|
| `group` | path | string(uuid)                                                                         | true     | Group ID                       |
| `body`  | body | [codersdk.UpsertGroupAIBudgetRequest](schemas.md#codersdkupsertgroupaibudgetrequest) | true     | Upsert group AI budget request |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                     |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupAIBudget](schemas.md#codersdkgroupaibudget) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete group AI budget

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/groups/{group}/ai/budget \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/groups/{group}/ai/budget`

### Parameters

| Name    | In   | Type         | Required | Description |
|---------|------|--------------|----------|-------------|
| `group` | path | string(uuid) | true     | Group ID    |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group AI spend

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/groups/{group}/ai/spend \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/groups/{group}/ai/spend`

Returns the AI spend limit and aggregate spend for the group.

### Parameters

| Name    | In   | Type         | Required | Description |
|---------|------|--------------|----------|-------------|
| `group` | path | string(uuid) | true     | Group ID    |

### Example responses

> 200 Response

```json
{
  "current_spend_micros": 0,
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z",
  "spend_limit_micros": 0,
  "total_spend_limit_micros": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupAISpend](schemas.md#codersdkgroupaispend) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group members by group ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/groups/{group}/members \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/groups/{group}/members`

### Parameters

| Name       | In    | Type         | Required | Description         |
|------------|-------|--------------|----------|---------------------|
| `group`    | path  | string       | true     | Group id            |
| `q`        | query | string       | false    | Member search query |
| `after_id` | query | string(uuid) | false    | After ID            |
| `limit`    | query | integer      | false    | Page limit          |
| `offset`   | query | integer      | false    | Page offset         |

### Example responses

> 200 Response

```json
{
  "count": 0,
  "users": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupMembersResponse](schemas.md#codersdkgroupmembersresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group members AI spend

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/groups/{group}/members/ai/spend?user_ids=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/groups/{group}/members/ai/spend`

Returns aggregate AI spend attributed to the group per requested user.
A maximum of 100 user IDs may be requested per call, and requests with more are rejected, so callers are expected to batch across multiple requests.
User IDs that are not members of the group, or that the caller has no read access to, are silently omitted.

### Parameters

| Name       | In    | Type         | Required | Description                                    |
|------------|-------|--------------|----------|------------------------------------------------|
| `group`    | path  | string(uuid) | true     | Group ID                                       |
| `user_ids` | query | string       | true     | Comma-separated list of user IDs (maximum 100) |

### Example responses

> 200 Response

```json
{
  "members": [
    {
      "effective_budget": {
        "limit_source": "user_override",
        "spend_limit_micros": 0
      },
      "effective_group_id": "85e2b926-ddfb-4c66-b68e-b66e5acec6c0",
      "group_budget": {
        "limit_source": "user_override",
        "spend_limit_micros": 0
      },
      "group_spend_micros": 0,
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
    }
  ],
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                 |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupMembersAISpend](schemas.md#codersdkgroupmembersaispend) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get licenses

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/licenses \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/licenses`

### Example responses

> 200 Response

```json
[
  {
    "claims": {},
    "id": 0,
    "uploaded_at": "2019-08-24T14:15:22Z",
    "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                  |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.License](schemas.md#codersdklicense) |

<h3 id="get-licenses-responseschema">Response Schema</h3>

Status Code **200**

| Name            | Type              | Required | Restrictions | Description                                                                                                                                                                                             |
|-----------------|-------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`  | array             | false    |              |                                                                                                                                                                                                         |
| `» claims`      | object            | false    |              | Claims are the JWT claims asserted by the license.  Here we use a generic string map to ensure that all data from the server is parsed verbatim, not just the fields this version of Coder understands. |
| `» id`          | integer           | false    |              |                                                                                                                                                                                                         |
| `» uploaded_at` | string(date-time) | false    |              |                                                                                                                                                                                                         |
| `» uuid`        | string(uuid)      | false    |              |                                                                                                                                                                                                         |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Add new license

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/licenses \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/licenses`

> Body parameter

```json
{
  "license": "string"
}
```

### Parameters

| Name   | In   | Type                                                               | Required | Description         |
|--------|------|--------------------------------------------------------------------|----------|---------------------|
| `body` | body | [codersdk.AddLicenseRequest](schemas.md#codersdkaddlicenserequest) | true     | Add license request |

### Example responses

> 201 Response

```json
{
  "claims": {},
  "id": 0,
  "uploaded_at": "2019-08-24T14:15:22Z",
  "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                         |
|--------|--------------------------------------------------------------|-------------|------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.License](schemas.md#codersdklicense) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update license entitlements

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/licenses/refresh-entitlements \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/licenses/refresh-entitlements`

### Example responses

> 201 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                           |
|--------|--------------------------------------------------------------|-------------|--------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Request a trial license

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/licenses/trial \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/licenses/trial`

> Body parameter

```json
{
  "attribution_id": "6f882a62-1d45-46e1-b5f4-0abfea127010",
  "company_name": "Acme Corp",
  "country": "United States",
  "developers": "string",
  "email": "jane.doe@example.com",
  "first_name": "Jane",
  "job_title": "Engineering Manager",
  "last_name": "Doe",
  "phone_number": "+14155552671",
  "source": "aibridge_session_threads"
}
```

### Parameters

| Name   | In   | Type                                                                               | Required | Description           |
|--------|------|------------------------------------------------------------------------------------|----------|-----------------------|
| `body` | body | [codersdk.CreateTrialLicenseRequest](schemas.md#codersdkcreatetriallicenserequest) | true     | Trial license request |

### Example responses

> 201 Response

```json
{
  "claims": {},
  "id": 0,
  "uploaded_at": "2019-08-24T14:15:22Z",
  "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                         |
|--------|--------------------------------------------------------------|-------------|------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.License](schemas.md#codersdklicense) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete license

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/licenses/{id} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/licenses/{id}`

### Parameters

| Name | In   | Type           | Required | Description |
|------|------|----------------|----------|-------------|
| `id` | path | string(number) | true     | License ID  |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update notification template dispatch method

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/notifications/templates/{notification_template}/method \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/notifications/templates/{notification_template}/method`

### Parameters

| Name                    | In   | Type   | Required | Description                |
|-------------------------|------|--------|----------|----------------------------|
| `notification_template` | path | string | true     | Notification template UUID |

### Responses

| Status | Meaning                                                         | Description  | Schema |
|--------|-----------------------------------------------------------------|--------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | Success      |        |
| 304    | [Not Modified](https://tools.ietf.org/html/rfc7232#section-4.1) | Not modified |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get OAuth2 applications

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/oauth2-provider/apps \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/oauth2-provider/apps`

### Parameters

| Name      | In    | Type   | Required | Description                                  |
|-----------|-------|--------|----------|----------------------------------------------|
| `user_id` | query | string | false    | Filter by applications authorized for a user |

### Example responses

> 200 Response

```json
[
  {
    "callback_url": "string",
    "client_type": "confidential",
    "dynamically_registered": true,
    "endpoints": {
      "authorization": "string",
      "device_authorization": "string",
      "token": "string",
      "token_revoke": "string"
    },
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "redirect_uris": [
      "string"
    ],
    "scope": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.OAuth2ProviderApp](schemas.md#codersdkoauth2providerapp) |

<h3 id="get-oauth2-applications.-responseschema">Response Schema</h3>

Status Code **200**

| Name                       | Type                                                                 | Required | Restrictions | Description                                                                                                                                                                                             |
|----------------------------|----------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`             | array                                                                | false    |              |                                                                                                                                                                                                         |
| `» callback_url`           | string                                                               | false    |              | Deprecated: equal to the first entry of redirect_uris. Read redirect_uris instead.                                                                                                                      |
| `» client_type`            | [codersdk.OAuth2ClientType](schemas.md#codersdkoauth2clienttype)     | false    |              | Client type is "confidential" or "public".                                                                                                                                                              |
| `» dynamically_registered` | boolean                                                              | false    |              | Dynamically registered is true when the app registered itself through Dynamic Client Registration rather than being created by an admin.                                                                |
| `» endpoints`              | [codersdk.OAuth2AppEndpoints](schemas.md#codersdkoauth2appendpoints) | false    |              | Endpoints are included in the app response for easier discovery. The OAuth2 spec does not have a defined place to find these (for comparison, OIDC has a '/.well-known/openid-configuration' endpoint). |
| `»» authorization`         | string                                                               | false    |              |                                                                                                                                                                                                         |
| `»» device_authorization`  | string                                                               | false    |              | Device authorization is optional.                                                                                                                                                                       |
| `»» token`                 | string                                                               | false    |              |                                                                                                                                                                                                         |
| `»» token_revoke`          | string                                                               | false    |              |                                                                                                                                                                                                         |
| `» icon`                   | string                                                               | false    |              |                                                                                                                                                                                                         |
| `» id`                     | string(uuid)                                                         | false    |              |                                                                                                                                                                                                         |
| `» name`                   | string                                                               | false    |              |                                                                                                                                                                                                         |
| `» redirect_uris`          | array                                                                | false    |              | Redirect uris are the app's registered redirect URIs, primary first.                                                                                                                                    |
| `» scope`                  | string                                                               | false    |              | Scope is the space-separated list of scopes this app's tokens may be granted. Empty means unrestricted. A non-empty value with no names is a configured allowlist that grants nothing.                  |

#### Enumerated Values

| Property      | Value(s)                 |
|---------------|--------------------------|
| `client_type` | `confidential`, `public` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create OAuth2 application

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/oauth2-provider/apps \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/oauth2-provider/apps`

> Body parameter

```json
{
  "callback_url": "string",
  "icon": "string",
  "name": "string",
  "redirect_uris": [
    "string"
  ],
  "scope": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                     | Required | Description                       |
|--------|------|------------------------------------------------------------------------------------------|----------|-----------------------------------|
| `body` | body | [codersdk.PostOAuth2ProviderAppRequest](schemas.md#codersdkpostoauth2providerapprequest) | true     | The OAuth2 application to create. |

### Example responses

> 200 Response

```json
{
  "callback_url": "string",
  "client_type": "confidential",
  "dynamically_registered": true,
  "endpoints": {
    "authorization": "string",
    "device_authorization": "string",
    "token": "string",
    "token_revoke": "string"
  },
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "redirect_uris": [
    "string"
  ],
  "scope": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OAuth2ProviderApp](schemas.md#codersdkoauth2providerapp) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get OAuth2 application

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/oauth2-provider/apps/{app} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/oauth2-provider/apps/{app}`

### Parameters

| Name  | In   | Type   | Required | Description |
|-------|------|--------|----------|-------------|
| `app` | path | string | true     | App ID      |

### Example responses

> 200 Response

```json
{
  "callback_url": "string",
  "client_type": "confidential",
  "dynamically_registered": true,
  "endpoints": {
    "authorization": "string",
    "device_authorization": "string",
    "token": "string",
    "token_revoke": "string"
  },
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "redirect_uris": [
    "string"
  ],
  "scope": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OAuth2ProviderApp](schemas.md#codersdkoauth2providerapp) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update OAuth2 application

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/oauth2-provider/apps/{app} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/oauth2-provider/apps/{app}`

> Body parameter

```json
{
  "callback_url": "string",
  "icon": "string",
  "name": "string",
  "redirect_uris": [
    "string"
  ],
  "scope": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                   | Required | Description                   |
|--------|------|----------------------------------------------------------------------------------------|----------|-------------------------------|
| `app`  | path | string                                                                                 | true     | App ID                        |
| `body` | body | [codersdk.PutOAuth2ProviderAppRequest](schemas.md#codersdkputoauth2providerapprequest) | true     | Update an OAuth2 application. |

### Example responses

> 200 Response

```json
{
  "callback_url": "string",
  "client_type": "confidential",
  "dynamically_registered": true,
  "endpoints": {
    "authorization": "string",
    "device_authorization": "string",
    "token": "string",
    "token_revoke": "string"
  },
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "redirect_uris": [
    "string"
  ],
  "scope": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OAuth2ProviderApp](schemas.md#codersdkoauth2providerapp) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete OAuth2 application

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/oauth2-provider/apps/{app} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/oauth2-provider/apps/{app}`

### Parameters

| Name  | In   | Type   | Required | Description |
|-------|------|--------|----------|-------------|
| `app` | path | string | true     | App ID      |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get OAuth2 application secrets

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/oauth2-provider/apps/{app}/secrets \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/oauth2-provider/apps/{app}/secrets`

### Parameters

| Name  | In   | Type   | Required | Description |
|-------|------|--------|----------|-------------|
| `app` | path | string | true     | App ID      |

### Example responses

> 200 Response

```json
[
  {
    "client_secret_truncated": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "last_used_at": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                  |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.OAuth2ProviderAppSecret](schemas.md#codersdkoauth2providerappsecret) |

<h3 id="get-oauth2-application-secrets.-responseschema">Response Schema</h3>

Status Code **200**

| Name                        | Type         | Required | Restrictions | Description |
|-----------------------------|--------------|----------|--------------|-------------|
| `[array item]`              | array        | false    |              |             |
| `» client_secret_truncated` | string       | false    |              |             |
| `» id`                      | string(uuid) | false    |              |             |
| `» last_used_at`            | string       | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create OAuth2 application secret

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/oauth2-provider/apps/{app}/secrets \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/oauth2-provider/apps/{app}/secrets`

### Parameters

| Name  | In   | Type   | Required | Description |
|-------|------|--------|----------|-------------|
| `app` | path | string | true     | App ID      |

### Example responses

> 200 Response

```json
[
  {
    "client_secret_full": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  }
]
```

### Responses

| Status | Meaning                                                          | Description                        | Schema                                                                                          |
|--------|------------------------------------------------------------------|------------------------------------|-------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)          | OK                                 | array of [codersdk.OAuth2ProviderAppSecretFull](schemas.md#codersdkoauth2providerappsecretfull) |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1) | Public clients cannot have secrets | [codersdk.Response](schemas.md#codersdkresponse)                                                |

<h3 id="create-oauth2-application-secret.-responseschema">Response Schema</h3>

Status Code **200**

| Name                   | Type         | Required | Restrictions | Description |
|------------------------|--------------|----------|--------------|-------------|
| `[array item]`         | array        | false    |              |             |
| `» client_secret_full` | string       | false    |              |             |
| `» id`                 | string(uuid) | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete OAuth2 application secret

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/oauth2-provider/apps/{app}/secrets/{secretID} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/oauth2-provider/apps/{app}/secrets/{secretID}`

### Parameters

| Name       | In   | Type   | Required | Description |
|------------|------|--------|----------|-------------|
| `app`      | path | string | true     | App ID      |
| `secretID` | path | string | true     | Secret ID   |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get OAuth2 provider settings

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/oauth2-provider/settings \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/oauth2-provider/settings`

### Example responses

> 200 Response

```json
{
  "dynamic_client_registration_enabled": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                       |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OAuth2ProviderSettings](schemas.md#codersdkoauth2providersettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update OAuth2 provider settings

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/oauth2-provider/settings \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/oauth2-provider/settings`

> Body parameter

```json
{
  "dynamic_client_registration_enabled": true
}
```

### Parameters

| Name   | In   | Type                                                                         | Required | Description                      |
|--------|------|------------------------------------------------------------------------------|----------|----------------------------------|
| `body` | body | [codersdk.OAuth2ProviderSettings](schemas.md#codersdkoauth2providersettings) | true     | OAuth2 provider settings request |

### Example responses

> 200 Response

```json
{
  "dynamic_client_registration_enabled": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                       |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OAuth2ProviderSettings](schemas.md#codersdkoauth2providersettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Export organization AI spend as CSV

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/ai/spend/export \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/ai/spend/export`

Returns per-user, per-group, per-model, per-provider aggregated AI spend for the organization as CSV, built from raw AI Gateway token usage.
The optional period_start and period_end query parameters bound the period and are interpreted as UTC. They must be provided together and span at most 31 days. When both are omitted, the current UTC monthly period is used.
An explicit period_start must fall within the configured AI Gateway data retention window, since older token usage is purged. The default period is narrowed to that window instead, and every row echoes the applied bounds.
Unknown query parameters are rejected.
Requires organization-level administrator permissions.

### Parameters

| Name            | In    | Type              | Required | Description                     |
|-----------------|-------|-------------------|----------|---------------------------------|
| `organization`  | path  | string(uuid)      | true     | Organization ID                 |
| `period_start`  | query | string(date-time) | false    | Inclusive lower bound (RFC3339) |
| `period_end`    | query | string(date-time) | false    | Exclusive upper bound (RFC3339) |
| `user_id`       | query | string(uuid)      | false    | User ID                         |
| `group_id`      | query | string(uuid)      | false    | Effective group ID              |
| `provider_name` | query | string            | false    | Configured provider name        |
| `model`         | query | string            | false    | Model name                      |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get groups by organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/groups`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  {
    "avatar_url": "http://example.com",
    "display_name": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "members": [
      {
        "avatar_url": "http://example.com",
        "created_at": "2019-08-24T14:15:22Z",
        "email": "user@example.com",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "is_service_account": true,
        "last_seen_at": "2019-08-24T14:15:22Z",
        "login_type": "",
        "name": "string",
        "status": "active",
        "theme_preference": "string",
        "updated_at": "2019-08-24T14:15:22Z",
        "username": "string"
      }
    ],
    "name": "string",
    "organization_display_name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_name": "string",
    "quota_allowance": 0,
    "source": "user",
    "total_member_count": 0
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                              |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Group](schemas.md#codersdkgroup) |

<h3 id="get-groups-by-organization-responseschema">Response Schema</h3>

Status Code **200**

| Name                          | Type                                                   | Required | Restrictions | Description                                                                                                                                                           |
|-------------------------------|--------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                | array                                                  | false    |              |                                                                                                                                                                       |
| `» avatar_url`                | string(uri)                                            | false    |              |                                                                                                                                                                       |
| `» display_name`              | string                                                 | false    |              |                                                                                                                                                                       |
| `» id`                        | string(uuid)                                           | false    |              |                                                                                                                                                                       |
| `» members`                   | array                                                  | false    |              |                                                                                                                                                                       |
| `»» avatar_url`               | string(uri)                                            | false    |              |                                                                                                                                                                       |
| `»» created_at`               | string(date-time)                                      | true     |              |                                                                                                                                                                       |
| `»» email`                    | string(email)                                          | true     |              |                                                                                                                                                                       |
| `»» id`                       | string(uuid)                                           | true     |              |                                                                                                                                                                       |
| `»» is_service_account`       | boolean                                                | false    |              |                                                                                                                                                                       |
| `»» last_seen_at`             | string(date-time)                                      | false    |              |                                                                                                                                                                       |
| `»» login_type`               | [codersdk.LoginType](schemas.md#codersdklogintype)     | false    |              |                                                                                                                                                                       |
| `»» name`                     | string                                                 | false    |              |                                                                                                                                                                       |
| `»» status`                   | [codersdk.UserStatus](schemas.md#codersdkuserstatus)   | false    |              |                                                                                                                                                                       |
| `»» theme_preference`         | string                                                 | false    |              | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead.                                                                            |
| `»» updated_at`               | string(date-time)                                      | false    |              |                                                                                                                                                                       |
| `»» username`                 | string                                                 | true     |              |                                                                                                                                                                       |
| `» name`                      | string                                                 | false    |              |                                                                                                                                                                       |
| `» organization_display_name` | string                                                 | false    |              |                                                                                                                                                                       |
| `» organization_id`           | string(uuid)                                           | false    |              |                                                                                                                                                                       |
| `» organization_name`         | string                                                 | false    |              |                                                                                                                                                                       |
| `» quota_allowance`           | integer                                                | false    |              |                                                                                                                                                                       |
| `» source`                    | [codersdk.GroupSource](schemas.md#codersdkgroupsource) | false    |              |                                                                                                                                                                       |
| `» total_member_count`        | integer                                                | false    |              | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. |

#### Enumerated Values

| Property     | Value(s)                                          |
|--------------|---------------------------------------------------|
| `login_type` | ``, `github`, `none`, `oidc`, `password`, `token` |
| `status`     | `active`, `suspended`                             |
| `source`     | `oidc`, `user`                                    |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create group for organization

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/groups \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations/{organization}/groups`

> Body parameter

```json
{
  "avatar_url": "string",
  "display_name": "string",
  "name": "string",
  "quota_allowance": 0
}
```

### Parameters

| Name           | In   | Type                                                                 | Required | Description          |
|----------------|------|----------------------------------------------------------------------|----------|----------------------|
| `organization` | path | string                                                               | true     | Organization ID      |
| `body`         | body | [codersdk.CreateGroupRequest](schemas.md#codersdkcreategrouprequest) | true     | Create group request |

### Example responses

> 201 Response

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "source": "user",
  "total_member_count": 0
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                     |
|--------|--------------------------------------------------------------|-------------|--------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.Group](schemas.md#codersdkgroup) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get organization groups AI spend

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups/ai/spend?group_ids=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/groups/ai/spend`

Returns AI spend limits and aggregate spend for the requested groups.
A maximum of 100 group IDs may be requested per call, and requests with more are rejected, so callers are expected to batch across multiple requests.
Unknown or unreadable group IDs are silently omitted.

### Parameters

| Name           | In    | Type         | Required | Description                                     |
|----------------|-------|--------------|----------|-------------------------------------------------|
| `organization` | path  | string(uuid) | true     | Organization ID                                 |
| `group_ids`    | query | string       | true     | Comma-separated list of group IDs (maximum 100) |

### Example responses

> 200 Response

```json
{
  "groups": [
    {
      "current_spend_micros": 0,
      "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
      "spend_limit_micros": 0,
      "total_spend_limit_micros": 0
    }
  ],
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                             |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationGroupsAISpend](schemas.md#codersdkorganizationgroupsaispend) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group by organization and group name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups/{groupName} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/groups/{groupName}`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |
| `groupName`    | path | string       | true     | Group name      |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "source": "user",
  "total_member_count": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                     |
|--------|---------------------------------------------------------|-------------|--------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Group](schemas.md#codersdkgroup) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group members by organization and group name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups/{groupName}/members \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/groups/{groupName}/members`

### Parameters

| Name           | In    | Type         | Required | Description         |
|----------------|-------|--------------|----------|---------------------|
| `organization` | path  | string(uuid) | true     | Organization ID     |
| `groupName`    | path  | string       | true     | Group name          |
| `q`            | query | string       | false    | Member search query |
| `after_id`     | query | string(uuid) | false    | After ID            |
| `limit`        | query | integer      | false    | Page limit          |
| `offset`       | query | integer      | false    | Page offset         |

### Example responses

> 200 Response

```json
{
  "count": 0,
  "users": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupMembersResponse](schemas.md#codersdkgroupmembersresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group members AI spend by organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups/{groupName}/members/ai/spend?user_ids=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/groups/{groupName}/members/ai/spend`

Returns aggregate AI spend attributed to the group per requested user.
A maximum of 100 user IDs may be requested per call, and requests with more are rejected, so callers are expected to batch across multiple requests.
User IDs that are not members of the group, or that the caller has no read access to, are silently omitted.

### Parameters

| Name           | In    | Type         | Required | Description                                    |
|----------------|-------|--------------|----------|------------------------------------------------|
| `organization` | path  | string(uuid) | true     | Organization ID                                |
| `groupName`    | path  | string       | true     | Group name                                     |
| `user_ids`     | query | string       | true     | Comma-separated list of user IDs (maximum 100) |

### Example responses

> 200 Response

```json
{
  "members": [
    {
      "effective_budget": {
        "limit_source": "user_override",
        "spend_limit_micros": 0
      },
      "effective_group_id": "85e2b926-ddfb-4c66-b68e-b66e5acec6c0",
      "group_budget": {
        "limit_source": "user_override",
        "spend_limit_micros": 0
      },
      "group_spend_micros": 0,
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
    }
  ],
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                 |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupMembersAISpend](schemas.md#codersdkgroupmembersaispend) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace quota by user

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/members/{user}/workspace-quota \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/members/{user}/workspace-quota`

### Parameters

| Name           | In   | Type         | Required | Description          |
|----------------|------|--------------|----------|----------------------|
| `user`         | path | string       | true     | User ID, name, or me |
| `organization` | path | string(uuid) | true     | Organization ID      |

### Example responses

> 200 Response

```json
{
  "budget": 0,
  "credits_consumed": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceQuota](schemas.md#codersdkworkspacequota) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get groups by organization (paginated)

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/paginated-groups \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/paginated-groups`

Unlike "Get groups by organization" (GET /organizations/{organization}/groups),
which authorizes each group individually via its ACL, this endpoint requires
organization-wide group read permission and does no per-group filtering. It is
therefore not a drop-in replacement: callers without org-wide group read receive
an error rather than a filtered subset.

The `q` parameter uses the shared filter syntax. Bare terms (including multi-word)
perform a free-text search over group name and display name. `search:` is the only
accepted key and unknown keys return 400. Because group display names may contain
colons, a value with a colon must be quoted, e.g. `search:"team: frontend"`; an
unquoted colon fails with `Query element "team:" cannot start or end with ':'`.

This endpoint returns group summaries without the member roster: each group
carries only `total_member_count` and no `members` field. Callers that need the
roster use the group members endpoint (GET /groups/{group}/members).

### Parameters

| Name           | In    | Type         | Required | Description                                                 |
|----------------|-------|--------------|----------|-------------------------------------------------------------|
| `organization` | path  | string       | true     | Organization ID or name                                     |
| `q`            | query | string       | false    | Search query (see description for syntax and colon-quoting) |
| `limit`        | query | integer      | false    | Page limit                                                  |
| `offset`       | query | integer      | false    | Page offset                                                 |
| `after_id`     | query | string(uuid) | false    | After ID                                                    |

### Example responses

> 200 Response

```json
{
  "count": 0,
  "groups": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "source": "user",
      "total_member_count": 0
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                         |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.PaginatedGroupsResponse](schemas.md#codersdkpaginatedgroupsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Serve provisioner daemon

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisionerdaemons/serve \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/provisionerdaemons/serve`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Responses

| Status | Meaning                                                                  | Description         | Schema |
|--------|--------------------------------------------------------------------------|---------------------|--------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List provisioner key

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisionerkeys \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/provisionerkeys`

### Parameters

| Name           | In   | Type   | Required | Description     |
|----------------|------|--------|----------|-----------------|
| `organization` | path | string | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "organization": "452c1a86-a0af-475b-b03f-724878b0f387",
    "tags": {
      "property1": "string",
      "property2": "string"
    }
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ProvisionerKey](schemas.md#codersdkprovisionerkey) |

<h3 id="list-provisioner-key-responseschema">Response Schema</h3>

Status Code **200**

| Name                | Type                                                                 | Required | Restrictions | Description |
|---------------------|----------------------------------------------------------------------|----------|--------------|-------------|
| `[array item]`      | array                                                                | false    |              |             |
| `» created_at`      | string(date-time)                                                    | false    |              |             |
| `» id`              | string(uuid)                                                         | false    |              |             |
| `» name`            | string                                                               | false    |              |             |
| `» organization`    | string(uuid)                                                         | false    |              |             |
| `» tags`            | [codersdk.ProvisionerKeyTags](schemas.md#codersdkprovisionerkeytags) | false    |              |             |
| `»» [any property]` | string                                                               | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create provisioner key

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/provisionerkeys \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations/{organization}/provisionerkeys`

### Parameters

| Name           | In   | Type   | Required | Description     |
|----------------|------|--------|----------|-----------------|
| `organization` | path | string | true     | Organization ID |

### Example responses

> 201 Response

```json
{
  "key": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                                                   |
|--------|--------------------------------------------------------------|-------------|------------------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.CreateProvisionerKeyResponse](schemas.md#codersdkcreateprovisionerkeyresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List provisioner key daemons

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisionerkeys/daemons \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/provisionerkeys/daemons`

### Parameters

| Name           | In   | Type   | Required | Description     |
|----------------|------|--------|----------|-----------------|
| `organization` | path | string | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  {
    "daemons": [
      {
        "api_version": "string",
        "created_at": "2019-08-24T14:15:22Z",
        "current_job": {
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "status": "pending",
          "template_display_name": "string",
          "template_icon": "string",
          "template_name": "string"
        },
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
        "key_name": "string",
        "last_seen_at": "2019-08-24T14:15:22Z",
        "name": "string",
        "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
        "previous_job": {
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "status": "pending",
          "template_display_name": "string",
          "template_icon": "string",
          "template_name": "string"
        },
        "provisioners": [
          "string"
        ],
        "status": "offline",
        "tags": {
          "property1": "string",
          "property2": "string"
        },
        "version": "string"
      }
    ],
    "key": {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "organization": "452c1a86-a0af-475b-b03f-724878b0f387",
      "tags": {
        "property1": "string",
        "property2": "string"
      }
    }
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                              |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ProvisionerKeyDaemons](schemas.md#codersdkprovisionerkeydaemons) |

<h3 id="list-provisioner-key-daemons-responseschema">Response Schema</h3>

Status Code **200**

| Name                        | Type                                                                           | Required | Restrictions | Description      |
|-----------------------------|--------------------------------------------------------------------------------|----------|--------------|------------------|
| `[array item]`              | array                                                                          | false    |              |                  |
| `» daemons`                 | array                                                                          | false    |              |                  |
| `»» api_version`            | string                                                                         | false    |              |                  |
| `»» created_at`             | string(date-time)                                                              | false    |              |                  |
| `»» current_job`            | [codersdk.ProvisionerDaemonJob](schemas.md#codersdkprovisionerdaemonjob)       | false    |              |                  |
| `»»» id`                    | string(uuid)                                                                   | false    |              |                  |
| `»»» status`                | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus)       | false    |              |                  |
| `»»» template_display_name` | string                                                                         | false    |              |                  |
| `»»» template_icon`         | string                                                                         | false    |              |                  |
| `»»» template_name`         | string                                                                         | false    |              |                  |
| `»» id`                     | string(uuid)                                                                   | false    |              |                  |
| `»» key_id`                 | string(uuid)                                                                   | false    |              |                  |
| `»» key_name`               | string                                                                         | false    |              | Optional fields. |
| `»» last_seen_at`           | string(date-time)                                                              | false    |              |                  |
| `»» name`                   | string                                                                         | false    |              |                  |
| `»» organization_id`        | string(uuid)                                                                   | false    |              |                  |
| `»» previous_job`           | [codersdk.ProvisionerDaemonJob](schemas.md#codersdkprovisionerdaemonjob)       | false    |              |                  |
| `»» provisioners`           | array                                                                          | false    |              |                  |
| `»» status`                 | [codersdk.ProvisionerDaemonStatus](schemas.md#codersdkprovisionerdaemonstatus) | false    |              |                  |
| `»» tags`                   | object                                                                         | false    |              |                  |
| `»»» [any property]`        | string                                                                         | false    |              |                  |
| `»» version`                | string                                                                         | false    |              |                  |
| `» key`                     | [codersdk.ProvisionerKey](schemas.md#codersdkprovisionerkey)                   | false    |              |                  |
| `»» created_at`             | string(date-time)                                                              | false    |              |                  |
| `»» id`                     | string(uuid)                                                                   | false    |              |                  |
| `»» name`                   | string                                                                         | false    |              |                  |
| `»» organization`           | string(uuid)                                                                   | false    |              |                  |
| `»» tags`                   | [codersdk.ProvisionerKeyTags](schemas.md#codersdkprovisionerkeytags)           | false    |              |                  |
| `»»» [any property]`        | string                                                                         | false    |              |                  |

#### Enumerated Values

| Property | Value(s)                                                                                        |
|----------|-------------------------------------------------------------------------------------------------|
| `status` | `busy`, `canceled`, `canceling`, `failed`, `idle`, `offline`, `pending`, `running`, `succeeded` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete provisioner key

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/organizations/{organization}/provisionerkeys/{provisionerkey} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/organizations/{organization}/provisionerkeys/{provisionerkey}`

### Parameters

| Name             | In   | Type   | Required | Description          |
|------------------|------|--------|----------|----------------------|
| `organization`   | path | string | true     | Organization ID      |
| `provisionerkey` | path | string | true     | Provisioner key name |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get the available organization idp sync claim fields

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/available-fields \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/settings/idpsync/available-fields`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  "string"
]
```

### Responses

| Status | Meaning                                                 | Description | Schema          |
|--------|---------------------------------------------------------|-------------|-----------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of string |

<h3 id="get-the-available-organization-idp-sync-claim-fields-responseschema">Response Schema</h3>

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get the organization idp sync claim field values

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/field-values?claimField=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/settings/idpsync/field-values`

### Parameters

| Name           | In    | Type           | Required | Description     |
|----------------|-------|----------------|----------|-----------------|
| `organization` | path  | string(uuid)   | true     | Organization ID |
| `claimField`   | query | string(string) | true     | Claim Field     |

### Example responses

> 200 Response

```json
[
  "string"
]
```

### Responses

| Status | Meaning                                                 | Description | Schema          |
|--------|---------------------------------------------------------|-------------|-----------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of string |

<h3 id="get-the-organization-idp-sync-claim-field-values-responseschema">Response Schema</h3>

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get group IdP Sync settings by organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/groups \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/settings/idpsync/groups`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
{
  "auto_create_missing_groups": true,
  "field": "string",
  "legacy_group_name_mapping": {
    "property1": "string",
    "property2": "string"
  },
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "regex_filter": {}
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupSyncSettings](schemas.md#codersdkgroupsyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update group IdP Sync settings by organization

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/groups \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/organizations/{organization}/settings/idpsync/groups`

> Body parameter

```json
{
  "auto_create_missing_groups": true,
  "field": "string",
  "legacy_group_name_mapping": {
    "property1": "string",
    "property2": "string"
  },
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "regex_filter": {}
}
```

### Parameters

| Name           | In   | Type                                                               | Required | Description     |
|----------------|------|--------------------------------------------------------------------|----------|-----------------|
| `organization` | path | string(uuid)                                                       | true     | Organization ID |
| `body`         | body | [codersdk.GroupSyncSettings](schemas.md#codersdkgroupsyncsettings) | true     | New settings    |

### Example responses

> 200 Response

```json
{
  "auto_create_missing_groups": true,
  "field": "string",
  "legacy_group_name_mapping": {
    "property1": "string",
    "property2": "string"
  },
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "regex_filter": {}
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupSyncSettings](schemas.md#codersdkgroupsyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update group IdP Sync config

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/groups/config \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/organizations/{organization}/settings/idpsync/groups/config`

> Body parameter

```json
{
  "auto_create_missing_groups": true,
  "field": "string",
  "regex_filter": {}
}
```

### Parameters

| Name           | In   | Type                                                                                         | Required | Description             |
|----------------|------|----------------------------------------------------------------------------------------------|----------|-------------------------|
| `organization` | path | string(uuid)                                                                                 | true     | Organization ID or name |
| `body`         | body | [codersdk.PatchGroupIDPSyncConfigRequest](schemas.md#codersdkpatchgroupidpsyncconfigrequest) | true     | New config values       |

### Example responses

> 200 Response

```json
{
  "auto_create_missing_groups": true,
  "field": "string",
  "legacy_group_name_mapping": {
    "property1": "string",
    "property2": "string"
  },
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "regex_filter": {}
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupSyncSettings](schemas.md#codersdkgroupsyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update group IdP Sync mapping

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/groups/mapping \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/organizations/{organization}/settings/idpsync/groups/mapping`

> Body parameter

```json
{
  "add": [
    {
      "gets": "string",
      "given": "string"
    }
  ],
  "remove": [
    {
      "gets": "string",
      "given": "string"
    }
  ]
}
```

### Parameters

| Name           | In   | Type                                                                                           | Required | Description                                   |
|----------------|------|------------------------------------------------------------------------------------------------|----------|-----------------------------------------------|
| `organization` | path | string(uuid)                                                                                   | true     | Organization ID or name                       |
| `body`         | body | [codersdk.PatchGroupIDPSyncMappingRequest](schemas.md#codersdkpatchgroupidpsyncmappingrequest) | true     | Description of the mappings to add and remove |

### Example responses

> 200 Response

```json
{
  "auto_create_missing_groups": true,
  "field": "string",
  "legacy_group_name_mapping": {
    "property1": "string",
    "property2": "string"
  },
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "regex_filter": {}
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GroupSyncSettings](schemas.md#codersdkgroupsyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get role IdP Sync settings by organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/roles \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/settings/idpsync/roles`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.RoleSyncSettings](schemas.md#codersdkrolesyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update role IdP Sync settings by organization

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/roles \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/organizations/{organization}/settings/idpsync/roles`

> Body parameter

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  }
}
```

### Parameters

| Name           | In   | Type                                                             | Required | Description     |
|----------------|------|------------------------------------------------------------------|----------|-----------------|
| `organization` | path | string(uuid)                                                     | true     | Organization ID |
| `body`         | body | [codersdk.RoleSyncSettings](schemas.md#codersdkrolesyncsettings) | true     | New settings    |

### Example responses

> 200 Response

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.RoleSyncSettings](schemas.md#codersdkrolesyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update role IdP Sync config

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/roles/config \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/organizations/{organization}/settings/idpsync/roles/config`

> Body parameter

```json
{
  "field": "string"
}
```

### Parameters

| Name           | In   | Type                                                                                       | Required | Description             |
|----------------|------|--------------------------------------------------------------------------------------------|----------|-------------------------|
| `organization` | path | string(uuid)                                                                               | true     | Organization ID or name |
| `body`         | body | [codersdk.PatchRoleIDPSyncConfigRequest](schemas.md#codersdkpatchroleidpsyncconfigrequest) | true     | New config values       |

### Example responses

> 200 Response

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.RoleSyncSettings](schemas.md#codersdkrolesyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update role IdP Sync mapping

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/settings/idpsync/roles/mapping \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/organizations/{organization}/settings/idpsync/roles/mapping`

> Body parameter

```json
{
  "add": [
    {
      "gets": "string",
      "given": "string"
    }
  ],
  "remove": [
    {
      "gets": "string",
      "given": "string"
    }
  ]
}
```

### Parameters

| Name           | In   | Type                                                                                         | Required | Description                                   |
|----------------|------|----------------------------------------------------------------------------------------------|----------|-----------------------------------------------|
| `organization` | path | string(uuid)                                                                                 | true     | Organization ID or name                       |
| `body`         | body | [codersdk.PatchRoleIDPSyncMappingRequest](schemas.md#codersdkpatchroleidpsyncmappingrequest) | true     | Description of the mappings to add and remove |

### Example responses

> 200 Response

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.RoleSyncSettings](schemas.md#codersdkrolesyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace sharing settings for organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/settings/workspace-sharing \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/settings/workspace-sharing`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
{
  "shareable_workspace_owners": "none",
  "sharing_disabled": true,
  "sharing_globally_disabled": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceSharingSettings](schemas.md#codersdkworkspacesharingsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace sharing settings for organization

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization}/settings/workspace-sharing \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/organizations/{organization}/settings/workspace-sharing`

> Body parameter

```json
{
  "shareable_workspace_owners": "none",
  "sharing_disabled": true
}
```

### Parameters

| Name           | In   | Type                                                                                                       | Required | Description                |
|----------------|------|------------------------------------------------------------------------------------------------------------|----------|----------------------------|
| `organization` | path | string(uuid)                                                                                               | true     | Organization ID            |
| `body`         | body | [codersdk.UpdateWorkspaceSharingSettingsRequest](schemas.md#codersdkupdateworkspacesharingsettingsrequest) | true     | Workspace sharing settings |

### Example responses

> 200 Response

```json
{
  "shareable_workspace_owners": "none",
  "sharing_disabled": true,
  "sharing_globally_disabled": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceSharingSettings](schemas.md#codersdkworkspacesharingsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Fetch provisioner key details

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/provisionerkeys/{provisionerkey} \
  -H 'Accept: application/json'
```

`GET /api/v2/provisionerkeys/{provisionerkey}`

### Parameters

| Name             | In   | Type   | Required | Description     |
|------------------|------|--------|----------|-----------------|
| `provisionerkey` | path | string | true     | Provisioner Key |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "organization": "452c1a86-a0af-475b-b03f-724878b0f387",
  "tags": {
    "property1": "string",
    "property2": "string"
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ProvisionerKey](schemas.md#codersdkprovisionerkey) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get active replicas

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/replicas \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/replicas`

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "database_latency": 0,
    "error": "string",
    "hostname": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "region_id": 0,
    "relay_address": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                  |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Replica](schemas.md#codersdkreplica) |

<h3 id="get-active-replicas-responseschema">Response Schema</h3>

Status Code **200**

| Name                 | Type              | Required | Restrictions | Description                                                        |
|----------------------|-------------------|----------|--------------|--------------------------------------------------------------------|
| `[array item]`       | array             | false    |              |                                                                    |
| `» created_at`       | string(date-time) | false    |              | Created at is the timestamp when the replica was first seen.       |
| `» database_latency` | integer           | false    |              | Database latency is the latency in microseconds to the database.   |
| `» error`            | string            | false    |              | Error is the replica error.                                        |
| `» hostname`         | string            | false    |              | Hostname is the hostname of the replica.                           |
| `» id`               | string(uuid)      | false    |              | ID is the unique identifier for the replica.                       |
| `» region_id`        | integer           | false    |              | Region ID is the region of the replica.                            |
| `» relay_address`    | string            | false    |              | Relay address is the accessible address to relay DERP connections. |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get the available idp sync claim fields

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/settings/idpsync/available-fields \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/settings/idpsync/available-fields`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  "string"
]
```

### Responses

| Status | Meaning                                                 | Description | Schema          |
|--------|---------------------------------------------------------|-------------|-----------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of string |

<h3 id="get-the-available-idp-sync-claim-fields-responseschema">Response Schema</h3>

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get the idp sync claim field values

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/settings/idpsync/field-values?claimField=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/settings/idpsync/field-values`

### Parameters

| Name           | In    | Type           | Required | Description     |
|----------------|-------|----------------|----------|-----------------|
| `organization` | path  | string(uuid)   | true     | Organization ID |
| `claimField`   | query | string(string) | true     | Claim Field     |

### Example responses

> 200 Response

```json
[
  "string"
]
```

### Responses

| Status | Meaning                                                 | Description | Schema          |
|--------|---------------------------------------------------------|-------------|-----------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of string |

<h3 id="get-the-idp-sync-claim-field-values-responseschema">Response Schema</h3>

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get organization IdP Sync settings

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/settings/idpsync/organization \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/settings/idpsync/organization`

### Example responses

> 200 Response

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "organization_assign_default": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationSyncSettings](schemas.md#codersdkorganizationsyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update organization IdP Sync settings

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/settings/idpsync/organization \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/settings/idpsync/organization`

> Body parameter

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "organization_assign_default": true
}
```

### Parameters

| Name   | In   | Type                                                                             | Required | Description  |
|--------|------|----------------------------------------------------------------------------------|----------|--------------|
| `body` | body | [codersdk.OrganizationSyncSettings](schemas.md#codersdkorganizationsyncsettings) | true     | New settings |

### Example responses

> 200 Response

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "organization_assign_default": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationSyncSettings](schemas.md#codersdkorganizationsyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update organization IdP Sync config

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/settings/idpsync/organization/config \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/settings/idpsync/organization/config`

> Body parameter

```json
{
  "assign_default": true,
  "field": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                                       | Required | Description       |
|--------|------|------------------------------------------------------------------------------------------------------------|----------|-------------------|
| `body` | body | [codersdk.PatchOrganizationIDPSyncConfigRequest](schemas.md#codersdkpatchorganizationidpsyncconfigrequest) | true     | New config values |

### Example responses

> 200 Response

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "organization_assign_default": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationSyncSettings](schemas.md#codersdkorganizationsyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update organization IdP Sync mapping

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/settings/idpsync/organization/mapping \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/settings/idpsync/organization/mapping`

> Body parameter

```json
{
  "add": [
    {
      "gets": "string",
      "given": "string"
    }
  ],
  "remove": [
    {
      "gets": "string",
      "given": "string"
    }
  ]
}
```

### Parameters

| Name   | In   | Type                                                                                                         | Required | Description                                   |
|--------|------|--------------------------------------------------------------------------------------------------------------|----------|-----------------------------------------------|
| `body` | body | [codersdk.PatchOrganizationIDPSyncMappingRequest](schemas.md#codersdkpatchorganizationidpsyncmappingrequest) | true     | Description of the mappings to add and remove |

### Example responses

> 200 Response

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "organization_assign_default": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationSyncSettings](schemas.md#codersdkorganizationsyncsettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template ACLs

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templates/{template}/acl`

### Parameters

| Name       | In   | Type         | Required | Description |
|------------|------|--------------|----------|-------------|
| `template` | path | string(uuid) | true     | Template ID |

### Example responses

> 200 Response

```json
{
  "group": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "members": [
        {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        }
      ],
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "role": "admin",
      "source": "user",
      "total_member_count": 0
    }
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "has_ai_seat": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "organization_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "role": "admin",
      "roles": [
        {
          "display_name": "string",
          "name": "string",
          "organization_id": "string"
        }
      ],
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                 |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.TemplateACL](schemas.md#codersdktemplateacl) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update template ACL

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/templates/{template}/acl \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/templates/{template}/acl`

> Body parameter

```json
{
  "group_perms": {
    "8bd26b20-f3e8-48be-a903-46bb920cf671": "use",
    "<group_id>": "admin"
  },
  "user_perms": {
    "4df59e74-c027-470b-ab4d-cbba8963a5e9": "use",
    "<user_id>": "admin"
  }
}
```

### Parameters

| Name       | In   | Type                                                               | Required | Description                 |
|------------|------|--------------------------------------------------------------------|----------|-----------------------------|
| `template` | path | string(uuid)                                                       | true     | Template ID                 |
| `body`     | body | [codersdk.UpdateTemplateACL](schemas.md#codersdkupdatetemplateacl) | true     | Update template ACL request |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template available acl users/groups

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl/available \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templates/{template}/acl/available`

### Parameters

| Name       | In   | Type         | Required | Description |
|------------|------|--------------|----------|-------------|
| `template` | path | string(uuid) | true     | Template ID |

### Example responses

> 200 Response

```json
[
  {
    "groups": [
      {
        "avatar_url": "http://example.com",
        "display_name": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "members": [
          {
            "avatar_url": "http://example.com",
            "created_at": "2019-08-24T14:15:22Z",
            "email": "user@example.com",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "is_service_account": true,
            "last_seen_at": "2019-08-24T14:15:22Z",
            "login_type": "",
            "name": "string",
            "status": "active",
            "theme_preference": "string",
            "updated_at": "2019-08-24T14:15:22Z",
            "username": "string"
          }
        ],
        "name": "string",
        "organization_display_name": "string",
        "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
        "organization_name": "string",
        "quota_allowance": 0,
        "source": "user",
        "total_member_count": 0
      }
    ],
    "users": [
      {
        "avatar_url": "http://example.com",
        "created_at": "2019-08-24T14:15:22Z",
        "email": "user@example.com",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "is_service_account": true,
        "last_seen_at": "2019-08-24T14:15:22Z",
        "login_type": "",
        "name": "string",
        "status": "active",
        "theme_preference": "string",
        "updated_at": "2019-08-24T14:15:22Z",
        "username": "string"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                            |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ACLAvailable](schemas.md#codersdkaclavailable) |

<h3 id="get-template-available-acl-users/groups-responseschema">Response Schema</h3>

Status Code **200**

| Name                           | Type                                                   | Required | Restrictions | Description                                                                                                                                                           |
|--------------------------------|--------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                 | array                                                  | false    |              |                                                                                                                                                                       |
| `» groups`                     | array                                                  | false    |              |                                                                                                                                                                       |
| `»» avatar_url`                | string(uri)                                            | false    |              |                                                                                                                                                                       |
| `»» display_name`              | string                                                 | false    |              |                                                                                                                                                                       |
| `»» id`                        | string(uuid)                                           | false    |              |                                                                                                                                                                       |
| `»» members`                   | array                                                  | false    |              |                                                                                                                                                                       |
| `»»» avatar_url`               | string(uri)                                            | false    |              |                                                                                                                                                                       |
| `»»» created_at`               | string(date-time)                                      | true     |              |                                                                                                                                                                       |
| `»»» email`                    | string(email)                                          | true     |              |                                                                                                                                                                       |
| `»»» id`                       | string(uuid)                                           | true     |              |                                                                                                                                                                       |
| `»»» is_service_account`       | boolean                                                | false    |              |                                                                                                                                                                       |
| `»»» last_seen_at`             | string(date-time)                                      | false    |              |                                                                                                                                                                       |
| `»»» login_type`               | [codersdk.LoginType](schemas.md#codersdklogintype)     | false    |              |                                                                                                                                                                       |
| `»»» name`                     | string                                                 | false    |              |                                                                                                                                                                       |
| `»»» status`                   | [codersdk.UserStatus](schemas.md#codersdkuserstatus)   | false    |              |                                                                                                                                                                       |
| `»»» theme_preference`         | string                                                 | false    |              | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead.                                                                            |
| `»»» updated_at`               | string(date-time)                                      | false    |              |                                                                                                                                                                       |
| `»»» username`                 | string                                                 | true     |              |                                                                                                                                                                       |
| `»» name`                      | string                                                 | false    |              |                                                                                                                                                                       |
| `»» organization_display_name` | string                                                 | false    |              |                                                                                                                                                                       |
| `»» organization_id`           | string(uuid)                                           | false    |              |                                                                                                                                                                       |
| `»» organization_name`         | string                                                 | false    |              |                                                                                                                                                                       |
| `»» quota_allowance`           | integer                                                | false    |              |                                                                                                                                                                       |
| `»» source`                    | [codersdk.GroupSource](schemas.md#codersdkgroupsource) | false    |              |                                                                                                                                                                       |
| `»» total_member_count`        | integer                                                | false    |              | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. |
| `» users`                      | array                                                  | false    |              |                                                                                                                                                                       |

#### Enumerated Values

| Property     | Value(s)                                          |
|--------------|---------------------------------------------------|
| `login_type` | ``, `github`, `none`, `oidc`, `password`, `token` |
| `status`     | `active`, `suspended`                             |
| `source`     | `oidc`, `user`                                    |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Invalidate presets for template

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templates/{template}/prebuilds/invalidate \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templates/{template}/prebuilds/invalidate`

### Parameters

| Name       | In   | Type         | Required | Description |
|------------|------|--------------|----------|-------------|
| `template` | path | string(uuid) | true     | Template ID |

### Example responses

> 200 Response

```json
{
  "invalidated": [
    {
      "preset_name": "string",
      "template_name": "string",
      "template_version_name": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                             |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.InvalidatePresetsResponse](schemas.md#codersdkinvalidatepresetsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user AI budget override

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/ai/budget/override \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/ai/budget/override`

### Parameters

| Name   | In   | Type   | Required | Description              |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true     | User ID, username, or me |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserAIBudgetOverride](schemas.md#codersdkuseraibudgetoverride) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Upsert user AI budget override

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/ai/budget/override \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/ai/budget/override`

> Body parameter

```json
{
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0
}
```

### Parameters

| Name   | In   | Type                                                                                               | Required | Description                            |
|--------|------|----------------------------------------------------------------------------------------------------|----------|----------------------------------------|
| `user` | path | string                                                                                             | true     | User ID, username, or me               |
| `body` | body | [codersdk.UpsertUserAIBudgetOverrideRequest](schemas.md#codersdkupsertuseraibudgetoverriderequest) | true     | Upsert user AI budget override request |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                   |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserAIBudgetOverride](schemas.md#codersdkuseraibudgetoverride) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete user AI budget override

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/users/{user}/ai/budget/override \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/users/{user}/ai/budget/override`

### Parameters

| Name   | In   | Type   | Required | Description              |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true     | User ID, username, or me |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user AI spend

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/ai/spend \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/ai/spend`

### Parameters

| Name   | In   | Type   | Required | Description              |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true     | User ID, username, or me |

### Example responses

> 200 Response

```json
{
  "current_spend_micros": 0,
  "effective_budget": {
    "limit_source": "user_override",
    "spend_limit_micros": 0
  },
  "effective_group_id": "85e2b926-ddfb-4c66-b68e-b66e5acec6c0",
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserAISpendStatus](schemas.md#codersdkuseraispendstatus) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user quiet hours schedule

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/quiet-hours \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/quiet-hours`

### Parameters

| Name   | In   | Type         | Required | Description |
|--------|------|--------------|----------|-------------|
| `user` | path | string(uuid) | true     | User ID     |

### Example responses

> 200 Response

```json
[
  {
    "next": "2019-08-24T14:15:22Z",
    "raw_schedule": "string",
    "time": "string",
    "timezone": "string",
    "user_can_set": true,
    "user_set": true
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                                |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.UserQuietHoursScheduleResponse](schemas.md#codersdkuserquiethoursscheduleresponse) |

<h3 id="get-user-quiet-hours-schedule-responseschema">Response Schema</h3>

Status Code **200**

| Name             | Type              | Required | Restrictions | Description                                                                                                                                                                      |
|------------------|-------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`   | array             | false    |              |                                                                                                                                                                                  |
| `» next`         | string(date-time) | false    |              | Next is the next time that the quiet hours window will start.                                                                                                                    |
| `» raw_schedule` | string            | false    |              |                                                                                                                                                                                  |
| `» time`         | string            | false    |              | Time is the time of day that the quiet hours window starts in the given Timezone each day.                                                                                       |
| `» timezone`     | string            | false    |              | raw format from the cron expression, UTC if unspecified                                                                                                                          |
| `» user_can_set` | boolean           | false    |              | User can set is true if the user is allowed to set their own quiet hours schedule. If false, the user cannot set a custom schedule and the default schedule will always be used. |
| `» user_set`     | boolean           | false    |              | User set is true if the user has set their own quiet hours schedule. If false, the user is using the default schedule.                                                           |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user quiet hours schedule

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/quiet-hours \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/quiet-hours`

> Body parameter

```json
{
  "schedule": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                                   | Required | Description             |
|--------|------|--------------------------------------------------------------------------------------------------------|----------|-------------------------|
| `user` | path | string(uuid)                                                                                           | true     | User ID                 |
| `body` | body | [codersdk.UpdateUserQuietHoursScheduleRequest](schemas.md#codersdkupdateuserquiethoursschedulerequest) | true     | Update schedule request |

### Example responses

> 200 Response

```json
[
  {
    "next": "2019-08-24T14:15:22Z",
    "raw_schedule": "string",
    "time": "string",
    "timezone": "string",
    "user_can_set": true,
    "user_set": true
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                                |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.UserQuietHoursScheduleResponse](schemas.md#codersdkuserquiethoursscheduleresponse) |

<h3 id="update-user-quiet-hours-schedule-responseschema">Response Schema</h3>

Status Code **200**

| Name             | Type              | Required | Restrictions | Description                                                                                                                                                                      |
|------------------|-------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`   | array             | false    |              |                                                                                                                                                                                  |
| `» next`         | string(date-time) | false    |              | Next is the next time that the quiet hours window will start.                                                                                                                    |
| `» raw_schedule` | string            | false    |              |                                                                                                                                                                                  |
| `» time`         | string            | false    |              | Time is the time of day that the quiet hours window starts in the given Timezone each day.                                                                                       |
| `» timezone`     | string            | false    |              | raw format from the cron expression, UTC if unspecified                                                                                                                          |
| `» user_can_set` | boolean           | false    |              | User can set is true if the user is allowed to set their own quiet hours schedule. If false, the user cannot set a custom schedule and the default schedule will always be used. |
| `» user_set`     | boolean           | false    |              | User set is true if the user has set their own quiet hours schedule. If false, the user is using the default schedule.                                                           |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace quota by user deprecated

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspace-quota/{user} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspace-quota/{user}`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "budget": 0,
  "credits_consumed": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceQuota](schemas.md#codersdkworkspacequota) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace proxies

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceproxies \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceproxies`

### Example responses

> 200 Response

```json
[
  {
    "regions": [
      {
        "created_at": "2019-08-24T14:15:22Z",
        "deleted": true,
        "derp_enabled": true,
        "derp_only": true,
        "display_name": "string",
        "healthy": true,
        "icon_url": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string",
        "path_app_url": "string",
        "status": {
          "checked_at": "2019-08-24T14:15:22Z",
          "report": {
            "errors": [
              "string"
            ],
            "warnings": [
              "string"
            ]
          },
          "status": "ok"
        },
        "updated_at": "2019-08-24T14:15:22Z",
        "version": "string",
        "wildcard_hostname": "string"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                                                  |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.RegionsResponse-codersdk_WorkspaceProxy](schemas.md#codersdkregionsresponse-codersdk_workspaceproxy) |

<h3 id="get-workspace-proxies-responseschema">Response Schema</h3>

Status Code **200**

| Name                   | Type                                                                     | Required | Restrictions | Description                                                                                                                                                                       |
|------------------------|--------------------------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`         | array                                                                    | false    |              |                                                                                                                                                                                   |
| `» regions`            | array                                                                    | false    |              |                                                                                                                                                                                   |
| `»» created_at`        | string(date-time)                                                        | false    |              |                                                                                                                                                                                   |
| `»» deleted`           | boolean                                                                  | false    |              |                                                                                                                                                                                   |
| `»» derp_enabled`      | boolean                                                                  | false    |              |                                                                                                                                                                                   |
| `»» derp_only`         | boolean                                                                  | false    |              |                                                                                                                                                                                   |
| `»» display_name`      | string                                                                   | false    |              |                                                                                                                                                                                   |
| `»» healthy`           | boolean                                                                  | false    |              |                                                                                                                                                                                   |
| `»» icon_url`          | string                                                                   | false    |              |                                                                                                                                                                                   |
| `»» id`                | string(uuid)                                                             | false    |              |                                                                                                                                                                                   |
| `»» name`              | string                                                                   | false    |              |                                                                                                                                                                                   |
| `»» path_app_url`      | string                                                                   | false    |              | Path app URL is the URL to the base path for path apps. Optional unless wildcard_hostname is set. E.g. https://us.example.com                                                     |
| `»» status`            | [codersdk.WorkspaceProxyStatus](schemas.md#codersdkworkspaceproxystatus) | false    |              | Status is the latest status check of the proxy. This will be empty for deleted proxies. This value can be used to determine if a workspace proxy is healthy and ready to use.     |
| `»»» checked_at`       | string(date-time)                                                        | false    |              |                                                                                                                                                                                   |
| `»»» report`           | [codersdk.ProxyHealthReport](schemas.md#codersdkproxyhealthreport)       | false    |              | Report provides more information about the health of the workspace proxy.                                                                                                         |
| `»»»» errors`          | array                                                                    | false    |              | Errors are problems that prevent the workspace proxy from being healthy                                                                                                           |
| `»»»» warnings`        | array                                                                    | false    |              | Warnings do not prevent the workspace proxy from being healthy, but should be addressed.                                                                                          |
| `»»» status`           | [codersdk.ProxyHealthStatus](schemas.md#codersdkproxyhealthstatus)       | false    |              |                                                                                                                                                                                   |
| `»» updated_at`        | string(date-time)                                                        | false    |              |                                                                                                                                                                                   |
| `»» version`           | string                                                                   | false    |              |                                                                                                                                                                                   |
| `»» wildcard_hostname` | string                                                                   | false    |              | Wildcard hostname is the wildcard hostname for subdomain apps. E.g. *.us.example.com E.g.*--suffix.au.example.com Optional. Does not need to be on the same domain as PathAppURL. |

#### Enumerated Values

| Property | Value(s)                                         |
|----------|--------------------------------------------------|
| `status` | `ok`, `unhealthy`, `unreachable`, `unregistered` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create workspace proxy

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaceproxies \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaceproxies`

> Body parameter

```json
{
  "display_name": "string",
  "icon": "string",
  "name": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                   | Required | Description                    |
|--------|------|----------------------------------------------------------------------------------------|----------|--------------------------------|
| `body` | body | [codersdk.CreateWorkspaceProxyRequest](schemas.md#codersdkcreateworkspaceproxyrequest) | true     | Create workspace proxy request |

### Example responses

> 201 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "deleted": true,
  "derp_enabled": true,
  "derp_only": true,
  "display_name": "string",
  "healthy": true,
  "icon_url": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "path_app_url": "string",
  "status": {
    "checked_at": "2019-08-24T14:15:22Z",
    "report": {
      "errors": [
        "string"
      ],
      "warnings": [
        "string"
      ]
    },
    "status": "ok"
  },
  "updated_at": "2019-08-24T14:15:22Z",
  "version": "string",
  "wildcard_hostname": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                       |
|--------|--------------------------------------------------------------|-------------|--------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.WorkspaceProxy](schemas.md#codersdkworkspaceproxy) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace proxy

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaceproxies/{workspaceproxy}`

### Parameters

| Name             | In   | Type         | Required | Description      |
|------------------|------|--------------|----------|------------------|
| `workspaceproxy` | path | string(uuid) | true     | Proxy ID or name |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "deleted": true,
  "derp_enabled": true,
  "derp_only": true,
  "display_name": "string",
  "healthy": true,
  "icon_url": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "path_app_url": "string",
  "status": {
    "checked_at": "2019-08-24T14:15:22Z",
    "report": {
      "errors": [
        "string"
      ],
      "warnings": [
        "string"
      ]
    },
    "status": "ok"
  },
  "updated_at": "2019-08-24T14:15:22Z",
  "version": "string",
  "wildcard_hostname": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceProxy](schemas.md#codersdkworkspaceproxy) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete workspace proxy

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/workspaceproxies/{workspaceproxy}`

### Parameters

| Name             | In   | Type         | Required | Description      |
|------------------|------|--------------|----------|------------------|
| `workspaceproxy` | path | string(uuid) | true     | Proxy ID or name |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace proxy

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/workspaceproxies/{workspaceproxy}`

> Body parameter

```json
{
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "regenerate_token": true
}
```

### Parameters

| Name             | In   | Type                                                                   | Required | Description                    |
|------------------|------|------------------------------------------------------------------------|----------|--------------------------------|
| `workspaceproxy` | path | string(uuid)                                                           | true     | Proxy ID or name               |
| `body`           | body | [codersdk.PatchWorkspaceProxy](schemas.md#codersdkpatchworkspaceproxy) | true     | Update workspace proxy request |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "deleted": true,
  "derp_enabled": true,
  "derp_only": true,
  "display_name": "string",
  "healthy": true,
  "icon_url": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "path_app_url": "string",
  "status": {
    "checked_at": "2019-08-24T14:15:22Z",
    "report": {
      "errors": [
        "string"
      ],
      "warnings": [
        "string"
      ]
    },
    "status": "ok"
  },
  "updated_at": "2019-08-24T14:15:22Z",
  "version": "string",
  "wildcard_hostname": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceProxy](schemas.md#codersdkworkspaceproxy) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace external agent credentials

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/external-agent/{agent}/credentials \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/external-agent/{agent}/credentials`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |
| `agent`     | path | string       | true     | Agent name   |

### Example responses

> 200 Response

```json
{
  "agent_token": "string",
  "command": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ExternalAgentCredentials](schemas.md#codersdkexternalagentcredentials) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## OAuth2 authorization request (GET - show authorization page)

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/oauth2/authorize?client_id=string&response_type=code&code_challenge=string \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /oauth2/authorize`

### Parameters

| Name                    | In    | Type   | Required | Description                                                                                                                                                                                                                                                        |
|-------------------------|-------|--------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `client_id`             | query | string | true     | Client ID                                                                                                                                                                                                                                                          |
| `state`                 | query | string | false    | A random unguessable string, echoed back on the callback                                                                                                                                                                                                           |
| `response_type`         | query | string | true     | Response type                                                                                                                                                                                                                                                      |
| `redirect_uri`          | query | string | false    | Redirect here after authorization                                                                                                                                                                                                                                  |
| `scope`                 | query | string | false    | Space-separated scopes to request. Each must be supported by this deployment, and the app's allowlist, when it has one, must cover the permissions requested rather than name each scope. Defaults to that allowlist, or to coder:all for an app with no allowlist |
| `code_challenge`        | query | string | true     | PKCE code challenge, 43 to 128 characters from [A-Za-z0-9-._~] (RFC 7636)                                                                                                                                                                                          |
| `code_challenge_method` | query | string | false    | PKCE challenge method. S256 only; omitting it means S256                                                                                                                                                                                                           |
| `resource`              | query | string | false    | RFC 8707 resource indicator: an absolute URI without a fragment                                                                                                                                                                                                    |

#### Enumerated Values

| Parameter               | Value(s) |
|-------------------------|----------|
| `response_type`         | `code`   |
| `code_challenge_method` | `S256`   |

### Responses

| Status | Meaning                                                                    | Description                                                                                                   | Schema |
|--------|----------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | Returns HTML authorization page                                                                               |        |
| 302    | [Found](https://tools.ietf.org/html/rfc7231#section-6.4.3)                 | Redirects to the app's registered callback carrying an OAuth2 error (RFC 6749 4.1.2.1)                        |        |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | HTML error page. The failure names the redirect URI or the client, so RFC 6749 4.1.2.1 withholds the callback |        |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | HTML error page. One of the app's registered redirect URIs is not usable                                      |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## OAuth2 authorization request (POST - process authorization)

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/oauth2/authorize?client_id=string&response_type=code&code_challenge=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /oauth2/authorize`

### Parameters

| Name                    | In    | Type   | Required | Description                                                                                                                                                                                                                                                        |
|-------------------------|-------|--------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `client_id`             | query | string | true     | Client ID                                                                                                                                                                                                                                                          |
| `state`                 | query | string | false    | A random unguessable string, echoed back on the callback                                                                                                                                                                                                           |
| `response_type`         | query | string | true     | Response type                                                                                                                                                                                                                                                      |
| `redirect_uri`          | query | string | false    | Redirect here after authorization                                                                                                                                                                                                                                  |
| `scope`                 | query | string | false    | Space-separated scopes to request. Each must be supported by this deployment, and the app's allowlist, when it has one, must cover the permissions requested rather than name each scope. Defaults to that allowlist, or to coder:all for an app with no allowlist |
| `code_challenge`        | query | string | true     | PKCE code challenge, 43 to 128 characters from [A-Za-z0-9-._~] (RFC 7636)                                                                                                                                                                                          |
| `code_challenge_method` | query | string | false    | PKCE challenge method. S256 only; omitting it means S256                                                                                                                                                                                                           |
| `resource`              | query | string | false    | RFC 8707 resource indicator: an absolute URI without a fragment                                                                                                                                                                                                    |

#### Enumerated Values

| Parameter               | Value(s) |
|-------------------------|----------|
| `response_type`         | `code`   |
| `code_challenge_method` | `S256`   |

### Example responses

> 400 Response

```json
{
  "error": "invalid_request",
  "error_description": "string",
  "error_uri": "string"
}
```

### Responses

| Status | Meaning                                                                    | Description                                                                                                            | Schema                                                 |
|--------|----------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|
| 302    | [Found](https://tools.ietf.org/html/rfc7231#section-6.4.3)                 | Redirects to the app's registered callback carrying either an authorization code or an OAuth2 error (RFC 6749 4.1.2.1) |                                                        |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | The failure names the redirect URI or the client, so RFC 6749 4.1.2.1 withholds the callback                           | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error) |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | One of the app's registered redirect URIs is not usable                                                                | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get OAuth2 client configuration (RFC 7592)

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/oauth2/clients/{client_id} \
  -H 'Accept: application/json'
```

`GET /oauth2/clients/{client_id}`

### Parameters

| Name        | In   | Type   | Required | Description |
|-------------|------|--------|----------|-------------|
| `client_id` | path | string | true     | Client ID   |

### Example responses

> 200 Response

```json
{
  "client_id": "string",
  "client_id_issued_at": 0,
  "client_name": "string",
  "client_secret_expires_at": 0,
  "client_uri": "string",
  "contacts": [
    "string"
  ],
  "grant_types": [
    "authorization_code"
  ],
  "jwks": {},
  "jwks_uri": "string",
  "logo_uri": "string",
  "policy_uri": "string",
  "redirect_uris": [
    "string"
  ],
  "registration_access_token": "string",
  "registration_client_uri": "string",
  "response_types": [
    "code"
  ],
  "scope": "string",
  "software_id": "string",
  "software_version": "string",
  "token_endpoint_auth_method": "client_secret_basic",
  "tos_uri": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                             |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OAuth2ClientConfiguration](schemas.md#codersdkoauth2clientconfiguration) |

## Update OAuth2 client configuration (RFC 7592)

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/oauth2/clients/{client_id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'
```

`PUT /oauth2/clients/{client_id}`

> Body parameter

```json
{
  "client_name": "string",
  "client_uri": "string",
  "contacts": [
    "string"
  ],
  "grant_types": [
    "authorization_code"
  ],
  "jwks": {},
  "jwks_uri": "string",
  "logo_uri": "string",
  "policy_uri": "string",
  "redirect_uris": [
    "string"
  ],
  "response_types": [
    "code"
  ],
  "scope": "string",
  "software_id": "string",
  "software_statement": "string",
  "software_version": "string",
  "token_endpoint_auth_method": "client_secret_basic",
  "tos_uri": "string"
}
```

### Parameters

| Name        | In   | Type                                                                                           | Required | Description           |
|-------------|------|------------------------------------------------------------------------------------------------|----------|-----------------------|
| `client_id` | path | string                                                                                         | true     | Client ID             |
| `body`      | body | [codersdk.OAuth2ClientRegistrationRequest](schemas.md#codersdkoauth2clientregistrationrequest) | true     | Client update request |

### Example responses

> 200 Response

```json
{
  "client_id": "string",
  "client_id_issued_at": 0,
  "client_name": "string",
  "client_secret_expires_at": 0,
  "client_uri": "string",
  "contacts": [
    "string"
  ],
  "grant_types": [
    "authorization_code"
  ],
  "jwks": {},
  "jwks_uri": "string",
  "logo_uri": "string",
  "policy_uri": "string",
  "redirect_uris": [
    "string"
  ],
  "registration_access_token": "string",
  "registration_client_uri": "string",
  "response_types": [
    "code"
  ],
  "scope": "string",
  "software_id": "string",
  "software_version": "string",
  "token_endpoint_auth_method": "client_secret_basic",
  "tos_uri": "string"
}
```

### Responses

| Status | Meaning                                                                 | Description                | Schema                                                                             |
|--------|-------------------------------------------------------------------------|----------------------------|------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                 | OK                         | [codersdk.OAuth2ClientConfiguration](schemas.md#codersdkoauth2clientconfiguration) |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 4 MiB | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error)                             |

## Delete OAuth2 client registration (RFC 7592)

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/oauth2/clients/{client_id}

```

`DELETE /oauth2/clients/{client_id}`

### Parameters

| Name        | In   | Type   | Required | Description |
|-------------|------|--------|----------|-------------|
| `client_id` | path | string | true     | Client ID   |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

## OAuth2 dynamic client registration (RFC 7591)

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/oauth2/register \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json'
```

`POST /oauth2/register`

> Body parameter

```json
{
  "client_name": "string",
  "client_uri": "string",
  "contacts": [
    "string"
  ],
  "grant_types": [
    "authorization_code"
  ],
  "jwks": {},
  "jwks_uri": "string",
  "logo_uri": "string",
  "policy_uri": "string",
  "redirect_uris": [
    "string"
  ],
  "response_types": [
    "code"
  ],
  "scope": "string",
  "software_id": "string",
  "software_statement": "string",
  "software_version": "string",
  "token_endpoint_auth_method": "client_secret_basic",
  "tos_uri": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                           | Required | Description                 |
|--------|------|------------------------------------------------------------------------------------------------|----------|-----------------------------|
| `body` | body | [codersdk.OAuth2ClientRegistrationRequest](schemas.md#codersdkoauth2clientregistrationrequest) | true     | Client registration request |

### Example responses

> 201 Response

```json
{
  "client_id": "string",
  "client_id_issued_at": 0,
  "client_name": "string",
  "client_secret": "string",
  "client_secret_expires_at": 0,
  "client_uri": "string",
  "contacts": [
    "string"
  ],
  "grant_types": [
    "authorization_code"
  ],
  "jwks": {},
  "jwks_uri": "string",
  "logo_uri": "string",
  "policy_uri": "string",
  "redirect_uris": [
    "string"
  ],
  "registration_access_token": "string",
  "registration_client_uri": "string",
  "response_types": [
    "code"
  ],
  "scope": "string",
  "software_id": "string",
  "software_version": "string",
  "token_endpoint_auth_method": "client_secret_basic",
  "tos_uri": "string"
}
```

### Responses

| Status | Meaning                                                                 | Description                | Schema                                                                                           |
|--------|-------------------------------------------------------------------------|----------------------------|--------------------------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)            | Created                    | [codersdk.OAuth2ClientRegistrationResponse](schemas.md#codersdkoauth2clientregistrationresponse) |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 4 MiB | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error)                                           |

## Revoke OAuth2 tokens (RFC 7009)

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/oauth2/revoke \
  -H 'Accept: application/json' \
  -H 'Authorization: Basic Y2xpZW50X2lkOmNsaWVudF9zZWNyZXQ='
```

`POST /oauth2/revoke`

> Body parameter

```yaml
client_id: string
client_secret: string
token: string
token_type_hint: string

```

### Parameters

| Name                | In     | Type   | Required | Description                                                                                                                                                        |
|---------------------|--------|--------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `Authorization`     | header | string | false    | HTTP Basic credentials, the client_id as the username and the client_secret as the password. A confidential client sends these or the form fields below, not both. |
| `body`              | body   | object | false    |                                                                                                                                                                    |
| `» client_id`       | body   | string | false    | Client ID, required unless sent as the HTTP Basic username                                                                                                         |
| `» client_secret`   | body   | string | false    | Client secret, required for a confidential client unless sent as the HTTP Basic password. Public clients (token_endpoint_auth_method=none) send no secret.         |
| `» token`           | body   | string | true     | The token to revoke                                                                                                                                                |
| `» token_type_hint` | body   | string | false    | Hint about token type (access_token or refresh_token)                                                                                                              |

### Example responses

> 400 Response

```json
{
  "error": "invalid_request",
  "error_description": "string",
  "error_uri": "string"
}
```

### Responses

| Status | Meaning                                                                 | Description                                                                                                                                                           | Schema                                                 |
|--------|-------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                 | Token successfully revoked. A 200 does not confirm that the token existed or belonged to the client                                                                   |                                                        |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)        | invalid_request: a missing client_id or token, credentials in both the Authorization header and the body, client_secret in the URL query string, or a malformed token | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error) |
| 401    | [Unauthorized](https://tools.ietf.org/html/rfc7235#section-3.1)         | invalid_client: the client is unknown, or a confidential client did not present a valid secret                                                                        | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error) |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 4 MiB                                                                                                                                            | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error) |

## OAuth2 token exchange

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/oauth2/tokens \
  -H 'Accept: application/json'
```

`POST /oauth2/tokens`

> Body parameter

```yaml
client_id: string
client_secret: string
code: string
code_verifier: string
refresh_token: string
grant_type: authorization_code

```

### Parameters

| Name              | In   | Type   | Required | Description                                                                                                                                               |
|-------------------|------|--------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------|
| `body`            | body | object | false    |                                                                                                                                                           |
| `» client_id`     | body | string | false    | Client ID, required if grant_type=authorization_code                                                                                                      |
| `» client_secret` | body | string | false    | Client secret, required if grant_type=authorization_code and the client is confidential. Public clients (token_endpoint_auth_method=none) send no secret. |
| `» code`          | body | string | false    | Authorization code, required if grant_type=authorization_code                                                                                             |
| `» code_verifier` | body | string | false    | PKCE code verifier, required if grant_type=authorization_code. 43-128 characters per RFC 7636.                                                            |
| `» refresh_token` | body | string | false    | Refresh token, required if grant_type=refresh_token                                                                                                       |
| `» grant_type`    | body | string | true     | Grant type                                                                                                                                                |

#### Enumerated Values

| Parameter      | Value(s)                                                                            |
|----------------|-------------------------------------------------------------------------------------|
| `» grant_type` | `authorization_code`, `client_credentials`, `implicit`, `password`, `refresh_token` |

### Example responses

> 200 Response

```json
{
  "access_token": "string",
  "expires_in": 0,
  "expiry": "2019-08-24T14:15:22Z",
  "refresh_token": "string",
  "scope": "string",
  "token_type": "Bearer"
}
```

### Responses

| Status | Meaning                                                                 | Description                                                                                 | Schema                                                                 |
|--------|-------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                 | OK                                                                                          | [codersdk.OAuth2TokenResponse](schemas.md#codersdkoauth2tokenresponse) |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)        | invalid_request: client_secret in the URL query string, or a missing or malformed parameter | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error)                 |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 4 MiB                                                                  | [codersdk.OAuth2Error](schemas.md#codersdkoauth2error)                 |

## Delete OAuth2 application tokens

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/oauth2/tokens?client_id=string \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /oauth2/tokens`

### Parameters

| Name        | In    | Type   | Required | Description |
|-------------|-------|--------|----------|-------------|
| `client_id` | query | string | true     | Client ID   |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## SCIM 2.0: Service Provider Config

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/scim/v2/ServiceProviderConfig

```

`GET /scim/v2/ServiceProviderConfig`

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

## SCIM 2.0: Get users

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/scim/v2/Users \
  -H 'Authorization: API_KEY'
```

`GET /scim/v2/Users`

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## SCIM 2.0: Create new user

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/scim/v2/Users \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Authorization: API_KEY'
```

`POST /scim/v2/Users`

> Body parameter

```json
{
  "active": true,
  "emails": [
    {
      "display": "string",
      "primary": true,
      "type": "string",
      "value": "user@example.com"
    }
  ],
  "groups": [
    null
  ],
  "id": "string",
  "meta": {
    "resourceType": "string"
  },
  "name": {
    "familyName": "string",
    "givenName": "string"
  },
  "schemas": [
    "string"
  ],
  "userName": "string"
}
```

### Parameters

| Name   | In   | Type                                                 | Required | Description |
|--------|------|------------------------------------------------------|----------|-------------|
| `body` | body | [legacyscim.SCIMUser](schemas.md#legacyscimscimuser) | true     | New user    |

### Example responses

> 200 Response

```json
{
  "active": true,
  "emails": [
    {
      "display": "string",
      "primary": true,
      "type": "string",
      "value": "user@example.com"
    }
  ],
  "groups": [
    null
  ],
  "id": "string",
  "meta": {
    "resourceType": "string"
  },
  "name": {
    "familyName": "string",
    "givenName": "string"
  },
  "schemas": [
    "string"
  ],
  "userName": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                               |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [legacyscim.SCIMUser](schemas.md#legacyscimscimuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## SCIM 2.0: Get user by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/scim/v2/Users/{id} \
  -H 'Authorization: API_KEY'
```

`GET /scim/v2/Users/{id}`

### Parameters

| Name | In   | Type         | Required | Description |
|------|------|--------------|----------|-------------|
| `id` | path | string(uuid) | true     | User ID     |

### Responses

| Status | Meaning                                                        | Description | Schema |
|--------|----------------------------------------------------------------|-------------|--------|
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4) | Not Found   |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## SCIM 2.0: Replace user account

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/scim/v2/Users/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/scim+json' \
  -H 'Authorization: API_KEY'
```

`PUT /scim/v2/Users/{id}`

> Body parameter

```json
{
  "active": true,
  "emails": [
    {
      "display": "string",
      "primary": true,
      "type": "string",
      "value": "user@example.com"
    }
  ],
  "groups": [
    null
  ],
  "id": "string",
  "meta": {
    "resourceType": "string"
  },
  "name": {
    "familyName": "string",
    "givenName": "string"
  },
  "schemas": [
    "string"
  ],
  "userName": "string"
}
```

### Parameters

| Name   | In   | Type                                                 | Required | Description          |
|--------|------|------------------------------------------------------|----------|----------------------|
| `id`   | path | string(uuid)                                         | true     | User ID              |
| `body` | body | [legacyscim.SCIMUser](schemas.md#legacyscimscimuser) | true     | Replace user request |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## SCIM 2.0: Update user account

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/scim/v2/Users/{id} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/scim+json' \
  -H 'Authorization: API_KEY'
```

`PATCH /scim/v2/Users/{id}`

> Body parameter

```json
{
  "active": true,
  "emails": [
    {
      "display": "string",
      "primary": true,
      "type": "string",
      "value": "user@example.com"
    }
  ],
  "groups": [
    null
  ],
  "id": "string",
  "meta": {
    "resourceType": "string"
  },
  "name": {
    "familyName": "string",
    "givenName": "string"
  },
  "schemas": [
    "string"
  ],
  "userName": "string"
}
```

### Parameters

| Name   | In   | Type                                                 | Required | Description         |
|--------|------|------------------------------------------------------|----------|---------------------|
| `id`   | path | string(uuid)                                         | true     | User ID             |
| `body` | body | [legacyscim.SCIMUser](schemas.md#legacyscimscimuser) | true     | Update user request |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Files

Source: https://coder.com/docs/reference/api/files

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Upload file

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/files \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/x-tar' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/files`

> Body parameter

```yaml
file: string

```

### Parameters

| Name           | In     | Type   | Required | Description                                                                                    |
|----------------|--------|--------|----------|------------------------------------------------------------------------------------------------|
| `Content-Type` | header | string | true     | Content-Type must be `application/x-tar` or `application/zip`                                  |
| `body`         | body   | object | true     |                                                                                                |
| `» file`       | body   | binary | true     | File to be uploaded. If using tar format, file must conform to ustar (pax may cause problems). |

### Example responses

> 200 Response

```json
{
  "hash": "19686d84-b10d-4f90-b18e-84fd3fa038fd"
}
```

### Responses

| Status | Meaning                                                                 | Description                                                              | Schema                                                       |
|--------|-------------------------------------------------------------------------|--------------------------------------------------------------------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                 | Returns existing file if duplicate                                       | [codersdk.UploadResponse](schemas.md#codersdkuploadresponse) |
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)            | Returns newly created file                                               | [codersdk.UploadResponse](schemas.md#codersdkuploadresponse) |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 100 MiB, or a .zip archive exceeds it once expanded | [codersdk.Response](schemas.md#codersdkresponse)             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get file by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/files/{fileID} \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/files/{fileID}`

### Parameters

| Name     | In   | Type         | Required | Description |
|----------|------|--------------|----------|-------------|
| `fileID` | path | string(uuid) | true     | File ID     |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Git

Source: https://coder.com/docs/reference/api/git

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get user external auths

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/external-auth \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/external-auth`

### Example responses

> 200 Response

```json
{
  "authenticated": true,
  "created_at": "2019-08-24T14:15:22Z",
  "expires": "2019-08-24T14:15:22Z",
  "has_refresh_token": true,
  "provider_id": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "validate_error": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ExternalAuthLink](schemas.md#codersdkexternalauthlink) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get external auth by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/external-auth/{externalauth} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/external-auth/{externalauth}`

### Parameters

| Name           | In   | Type           | Required | Description     |
|----------------|------|----------------|----------|-----------------|
| `externalauth` | path | string(string) | true     | Git Provider ID |

### Example responses

> 200 Response

```json
{
  "app_install_url": "string",
  "app_installable": true,
  "authenticated": true,
  "device": true,
  "display_name": "string",
  "installations": [
    {
      "account": {
        "avatar_url": "string",
        "id": 0,
        "login": "string",
        "name": "string",
        "profile_url": "string"
      },
      "configure_url": "string",
      "id": 0
    }
  ],
  "supports_revocation": true,
  "user": {
    "avatar_url": "string",
    "id": 0,
    "login": "string",
    "name": "string",
    "profile_url": "string"
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ExternalAuth](schemas.md#codersdkexternalauth) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete external auth user link by ID

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/external-auth/{externalauth} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/external-auth/{externalauth}`

### Parameters

| Name           | In   | Type           | Required | Description     |
|----------------|------|----------------|----------|-----------------|
| `externalauth` | path | string(string) | true     | Git Provider ID |

### Example responses

> 200 Response

```json
{
  "token_revocation_error": "string",
  "token_revoked": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.DeleteExternalAuthByIDResponse](schemas.md#codersdkdeleteexternalauthbyidresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get external auth device by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/external-auth/{externalauth}/device \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/external-auth/{externalauth}/device`

### Parameters

| Name           | In   | Type           | Required | Description     |
|----------------|------|----------------|----------|-----------------|
| `externalauth` | path | string(string) | true     | Git Provider ID |

### Example responses

> 200 Response

```json
{
  "device_code": "string",
  "expires_in": 0,
  "interval": 0,
  "user_code": "string",
  "verification_uri": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                               |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ExternalAuthDevice](schemas.md#codersdkexternalauthdevice) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Post external auth device by ID

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/external-auth/{externalauth}/device \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/external-auth/{externalauth}/device`

### Parameters

| Name           | In   | Type           | Required | Description          |
|----------------|------|----------------|----------|----------------------|
| `externalauth` | path | string(string) | true     | External Provider ID |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# InitScript

Source: https://coder.com/docs/reference/api/initscript

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get agent init script

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/init-script/{os}/{arch}

```

`GET /api/v2/init-script/{os}/{arch}`

### Parameters

| Name   | In   | Type   | Required | Description      |
|--------|------|--------|----------|------------------|
| `os`   | path | string | true     | Operating system |
| `arch` | path | string | true     | Architecture     |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | Success     |        |

---

# Insights

Source: https://coder.com/docs/reference/api/insights

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get deployment DAUs

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/insights/daus?tz_offset=0 \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/insights/daus`

### Parameters

| Name        | In    | Type    | Required | Description                |
|-------------|-------|---------|----------|----------------------------|
| `tz_offset` | query | integer | true     | Time-zone offset (e.g. -2) |

### Example responses

> 200 Response

```json
{
  "entries": [
    {
      "amount": 0,
      "date": "string"
    }
  ],
  "tz_hour_offset": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.DAUsResponse](schemas.md#codersdkdausresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get insights about templates

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/insights/templates?start_time=2019-08-24T14%3A15%3A22Z&end_time=2019-08-24T14%3A15%3A22Z&interval=week \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/insights/templates`

### Parameters

| Name           | In    | Type              | Required | Description  |
|----------------|-------|-------------------|----------|--------------|
| `start_time`   | query | string(date-time) | true     | Start time   |
| `end_time`     | query | string(date-time) | true     | End time     |
| `interval`     | query | string            | true     | Interval     |
| `template_ids` | query | array[string]     | false    | Template IDs |

#### Enumerated Values

| Parameter  | Value(s)      |
|------------|---------------|
| `interval` | `day`, `week` |

### Example responses

> 200 Response

```json
{
  "interval_reports": [
    {
      "active_users": 14,
      "end_time": "2019-08-24T14:15:22Z",
      "interval": "week",
      "start_time": "2019-08-24T14:15:22Z",
      "template_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ]
    }
  ],
  "report": {
    "active_users": 22,
    "apps_usage": [
      {
        "display_name": "Visual Studio Code",
        "icon": "string",
        "seconds": 80500,
        "slug": "vscode",
        "template_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "times_used": 2,
        "type": "builtin"
      }
    ],
    "end_time": "2019-08-24T14:15:22Z",
    "parameters_usage": [
      {
        "description": "string",
        "display_name": "string",
        "name": "string",
        "options": [
          {
            "description": "string",
            "icon": "string",
            "name": "string",
            "value": "string"
          }
        ],
        "template_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "type": "string",
        "values": [
          {
            "count": 0,
            "value": "string"
          }
        ]
      }
    ],
    "start_time": "2019-08-24T14:15:22Z",
    "template_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ]
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.TemplateInsightsResponse](schemas.md#codersdktemplateinsightsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get insights about user activity

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/insights/user-activity?start_time=2019-08-24T14%3A15%3A22Z&end_time=2019-08-24T14%3A15%3A22Z \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/insights/user-activity`

### Parameters

| Name           | In    | Type              | Required | Description  |
|----------------|-------|-------------------|----------|--------------|
| `start_time`   | query | string(date-time) | true     | Start time   |
| `end_time`     | query | string(date-time) | true     | End time     |
| `template_ids` | query | array[string]     | false    | Template IDs |

### Example responses

> 200 Response

```json
{
  "report": {
    "end_time": "2019-08-24T14:15:22Z",
    "start_time": "2019-08-24T14:15:22Z",
    "template_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "users": [
      {
        "avatar_url": "http://example.com",
        "seconds": 80500,
        "template_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
        "username": "string"
      }
    ]
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserActivityInsightsResponse](schemas.md#codersdkuseractivityinsightsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get insights about user latency

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/insights/user-latency?start_time=2019-08-24T14%3A15%3A22Z&end_time=2019-08-24T14%3A15%3A22Z \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/insights/user-latency`

### Parameters

| Name           | In    | Type              | Required | Description  |
|----------------|-------|-------------------|----------|--------------|
| `start_time`   | query | string(date-time) | true     | Start time   |
| `end_time`     | query | string(date-time) | true     | End time     |
| `template_ids` | query | array[string]     | false    | Template IDs |

### Example responses

> 200 Response

```json
{
  "report": {
    "end_time": "2019-08-24T14:15:22Z",
    "start_time": "2019-08-24T14:15:22Z",
    "template_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "users": [
      {
        "avatar_url": "http://example.com",
        "latency_ms": {
          "p50": 31.312,
          "p95": 119.832
        },
        "template_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
        "username": "string"
      }
    ]
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                 |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserLatencyInsightsResponse](schemas.md#codersdkuserlatencyinsightsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get insights about user status counts

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/insights/user-status-counts \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/insights/user-status-counts`

### Parameters

| Name        | In    | Type    | Required | Description                                                   |
|-------------|-------|---------|----------|---------------------------------------------------------------|
| `timezone`  | query | string  | false    | IANA timezone name (e.g. America/St_Johns)                    |
| `tz_offset` | query | integer | false    | Deprecated: Time-zone offset (e.g. -2). Use timezone instead. |

### Example responses

> 200 Response

```json
{
  "status_counts": {
    "property1": [
      {
        "count": 10,
        "date": "2019-08-24T14:15:22Z"
      }
    ],
    "property2": [
      {
        "count": 10,
        "date": "2019-08-24T14:15:22Z"
      }
    ]
  }
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                 |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GetUserStatusCountsResponse](schemas.md#codersdkgetuserstatuscountsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# MCP

Source: https://coder.com/docs/reference/api/mcp

<!-- DO NOT EDIT | GENERATED CONTENT -->

---

# Members

Source: https://coder.com/docs/reference/api/members

<!-- DO NOT EDIT | GENERATED CONTENT -->

## List organization members

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/members \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/members`

### Parameters

| Name           | In   | Type   | Required | Description     |
|----------------|------|--------|----------|-----------------|
| `organization` | path | string | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  {
    "avatar_url": "string",
    "created_at": "2019-08-24T14:15:22Z",
    "email": "string",
    "global_roles": [
      {
        "display_name": "string",
        "name": "string",
        "organization_id": "string"
      }
    ],
    "has_ai_seat": true,
    "is_service_account": true,
    "last_seen_at": "2019-08-24T14:15:22Z",
    "login_type": "",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "roles": [
      {
        "display_name": "string",
        "name": "string",
        "organization_id": "string"
      }
    ],
    "status": "active",
    "updated_at": "2019-08-24T14:15:22Z",
    "user_created_at": "2019-08-24T14:15:22Z",
    "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
    "user_updated_at": "2019-08-24T14:15:22Z",
    "username": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                                |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.OrganizationMemberWithUserData](schemas.md#codersdkorganizationmemberwithuserdata) |

<h3 id="list-organization-members-responseschema">Response Schema</h3>

Status Code **200**

| Name                   | Type                                                 | Required | Restrictions | Description                                                                                      |
|------------------------|------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------|
| `[array item]`         | array                                                | false    |              |                                                                                                  |
| `» avatar_url`         | string                                               | false    |              |                                                                                                  |
| `» created_at`         | string(date-time)                                    | false    |              |                                                                                                  |
| `» email`              | string                                               | false    |              |                                                                                                  |
| `» global_roles`       | array                                                | false    |              |                                                                                                  |
| `»» display_name`      | string                                               | false    |              |                                                                                                  |
| `»» name`              | string                                               | false    |              |                                                                                                  |
| `»» organization_id`   | string                                               | false    |              |                                                                                                  |
| `» has_ai_seat`        | boolean                                              | false    |              | Has ai seat intentionally omits omitempty so the API always includes the field, even when false. |
| `» is_service_account` | boolean                                              | false    |              |                                                                                                  |
| `» last_seen_at`       | string(date-time)                                    | false    |              |                                                                                                  |
| `» login_type`         | [codersdk.LoginType](schemas.md#codersdklogintype)   | false    |              |                                                                                                  |
| `» name`               | string                                               | false    |              |                                                                                                  |
| `» organization_id`    | string(uuid)                                         | false    |              |                                                                                                  |
| `» roles`              | array                                                | false    |              |                                                                                                  |
| `» status`             | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false    |              |                                                                                                  |
| `» updated_at`         | string(date-time)                                    | false    |              |                                                                                                  |
| `» user_created_at`    | string(date-time)                                    | false    |              |                                                                                                  |
| `» user_id`            | string(uuid)                                         | false    |              |                                                                                                  |
| `» user_updated_at`    | string(date-time)                                    | false    |              |                                                                                                  |
| `» username`           | string                                               | false    |              |                                                                                                  |

#### Enumerated Values

| Property     | Value(s)                                          |
|--------------|---------------------------------------------------|
| `login_type` | ``, `github`, `none`, `oidc`, `password`, `token` |
| `status`     | `active`, `suspended`                             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get member roles by organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/members/roles \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/members/roles`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  {
    "assignable": true,
    "built_in": true,
    "display_name": "string",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_member_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "organization_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "site_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "user_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                  |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.AssignableRoles](schemas.md#codersdkassignableroles) |

<h3 id="get-member-roles-by-organization-responseschema">Response Schema</h3>

Status Code **200**

| Name                                | Type                                                     | Required | Restrictions | Description                                                                                            |
|-------------------------------------|----------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------|
| `[array item]`                      | array                                                    | false    |              |                                                                                                        |
| `» assignable`                      | boolean                                                  | false    |              |                                                                                                        |
| `» built_in`                        | boolean                                                  | false    |              | Built in roles are immutable                                                                           |
| `» display_name`                    | string                                                   | false    |              |                                                                                                        |
| `» name`                            | string                                                   | false    |              |                                                                                                        |
| `» organization_id`                 | string(uuid)                                             | false    |              |                                                                                                        |
| `» organization_member_permissions` | array                                                    | false    |              | Organization member permissions are specific for the organization in the field 'OrganizationID' above. |
| `»» action`                         | [codersdk.RBACAction](schemas.md#codersdkrbacaction)     | false    |              |                                                                                                        |
| `»» negate`                         | boolean                                                  | false    |              | Negate makes this a negative permission                                                                |
| `»» resource_type`                  | [codersdk.RBACResource](schemas.md#codersdkrbacresource) | false    |              |                                                                                                        |
| `» organization_permissions`        | array                                                    | false    |              | Organization permissions are specific for the organization in the field 'OrganizationID' above.        |
| `» site_permissions`                | array                                                    | false    |              |                                                                                                        |
| `» user_permissions`                | array                                                    | false    |              |                                                                                                        |

#### Enumerated Values

| Property        | Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action`        | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `chat_model_config`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `mcp_server_config`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_build_orchestration`, `workspace_dormant`, `workspace_proxy` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update a custom organization role

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/organizations/{organization}/members/roles \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/organizations/{organization}/members/roles`

> Body parameter

```json
{
  "display_name": "string",
  "name": "string",
  "organization_member_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "organization_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "site_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "user_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ]
}
```

### Parameters

| Name           | In   | Type                                                               | Required | Description         |
|----------------|------|--------------------------------------------------------------------|----------|---------------------|
| `organization` | path | string(uuid)                                                       | true     | Organization ID     |
| `body`         | body | [codersdk.CustomRoleRequest](schemas.md#codersdkcustomrolerequest) | true     | Update role request |

### Example responses

> 200 Response

```json
[
  {
    "display_name": "string",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_member_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "organization_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "site_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "user_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                            |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Role](schemas.md#codersdkrole) |

<h3 id="update-a-custom-organization-role-responseschema">Response Schema</h3>

Status Code **200**

| Name                                | Type                                                     | Required | Restrictions | Description                                                                                            |
|-------------------------------------|----------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------|
| `[array item]`                      | array                                                    | false    |              |                                                                                                        |
| `» display_name`                    | string                                                   | false    |              |                                                                                                        |
| `» name`                            | string                                                   | false    |              |                                                                                                        |
| `» organization_id`                 | string(uuid)                                             | false    |              |                                                                                                        |
| `» organization_member_permissions` | array                                                    | false    |              | Organization member permissions are specific for the organization in the field 'OrganizationID' above. |
| `»» action`                         | [codersdk.RBACAction](schemas.md#codersdkrbacaction)     | false    |              |                                                                                                        |
| `»» negate`                         | boolean                                                  | false    |              | Negate makes this a negative permission                                                                |
| `»» resource_type`                  | [codersdk.RBACResource](schemas.md#codersdkrbacresource) | false    |              |                                                                                                        |
| `» organization_permissions`        | array                                                    | false    |              | Organization permissions are specific for the organization in the field 'OrganizationID' above.        |
| `» site_permissions`                | array                                                    | false    |              |                                                                                                        |
| `» user_permissions`                | array                                                    | false    |              |                                                                                                        |

#### Enumerated Values

| Property        | Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action`        | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `chat_model_config`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `mcp_server_config`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_build_orchestration`, `workspace_dormant`, `workspace_proxy` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Insert a custom organization role

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/members/roles \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations/{organization}/members/roles`

> Body parameter

```json
{
  "display_name": "string",
  "name": "string",
  "organization_member_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "organization_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "site_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "user_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ]
}
```

### Parameters

| Name           | In   | Type                                                               | Required | Description         |
|----------------|------|--------------------------------------------------------------------|----------|---------------------|
| `organization` | path | string(uuid)                                                       | true     | Organization ID     |
| `body`         | body | [codersdk.CustomRoleRequest](schemas.md#codersdkcustomrolerequest) | true     | Insert role request |

### Example responses

> 200 Response

```json
[
  {
    "display_name": "string",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_member_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "organization_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "site_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "user_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                            |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Role](schemas.md#codersdkrole) |

<h3 id="insert-a-custom-organization-role-responseschema">Response Schema</h3>

Status Code **200**

| Name                                | Type                                                     | Required | Restrictions | Description                                                                                            |
|-------------------------------------|----------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------|
| `[array item]`                      | array                                                    | false    |              |                                                                                                        |
| `» display_name`                    | string                                                   | false    |              |                                                                                                        |
| `» name`                            | string                                                   | false    |              |                                                                                                        |
| `» organization_id`                 | string(uuid)                                             | false    |              |                                                                                                        |
| `» organization_member_permissions` | array                                                    | false    |              | Organization member permissions are specific for the organization in the field 'OrganizationID' above. |
| `»» action`                         | [codersdk.RBACAction](schemas.md#codersdkrbacaction)     | false    |              |                                                                                                        |
| `»» negate`                         | boolean                                                  | false    |              | Negate makes this a negative permission                                                                |
| `»» resource_type`                  | [codersdk.RBACResource](schemas.md#codersdkrbacresource) | false    |              |                                                                                                        |
| `» organization_permissions`        | array                                                    | false    |              | Organization permissions are specific for the organization in the field 'OrganizationID' above.        |
| `» site_permissions`                | array                                                    | false    |              |                                                                                                        |
| `» user_permissions`                | array                                                    | false    |              |                                                                                                        |

#### Enumerated Values

| Property        | Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action`        | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `chat_model_config`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `mcp_server_config`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_build_orchestration`, `workspace_dormant`, `workspace_proxy` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete a custom organization role

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/organizations/{organization}/members/roles/{roleName} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/organizations/{organization}/members/roles/{roleName}`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |
| `roleName`     | path | string       | true     | Role name       |

### Example responses

> 200 Response

```json
[
  {
    "display_name": "string",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_member_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "organization_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "site_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "user_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                            |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Role](schemas.md#codersdkrole) |

<h3 id="delete-a-custom-organization-role-responseschema">Response Schema</h3>

Status Code **200**

| Name                                | Type                                                     | Required | Restrictions | Description                                                                                            |
|-------------------------------------|----------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------|
| `[array item]`                      | array                                                    | false    |              |                                                                                                        |
| `» display_name`                    | string                                                   | false    |              |                                                                                                        |
| `» name`                            | string                                                   | false    |              |                                                                                                        |
| `» organization_id`                 | string(uuid)                                             | false    |              |                                                                                                        |
| `» organization_member_permissions` | array                                                    | false    |              | Organization member permissions are specific for the organization in the field 'OrganizationID' above. |
| `»» action`                         | [codersdk.RBACAction](schemas.md#codersdkrbacaction)     | false    |              |                                                                                                        |
| `»» negate`                         | boolean                                                  | false    |              | Negate makes this a negative permission                                                                |
| `»» resource_type`                  | [codersdk.RBACResource](schemas.md#codersdkrbacresource) | false    |              |                                                                                                        |
| `» organization_permissions`        | array                                                    | false    |              | Organization permissions are specific for the organization in the field 'OrganizationID' above.        |
| `» site_permissions`                | array                                                    | false    |              |                                                                                                        |
| `» user_permissions`                | array                                                    | false    |              |                                                                                                        |

#### Enumerated Values

| Property        | Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action`        | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `chat_model_config`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `mcp_server_config`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_build_orchestration`, `workspace_dormant`, `workspace_proxy` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get organization member

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/members/{user} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/members/{user}`

### Parameters

| Name           | In   | Type   | Required | Description          |
|----------------|------|--------|----------|----------------------|
| `organization` | path | string | true     | Organization ID      |
| `user`         | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "avatar_url": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "string",
  "global_roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "has_ai_seat": true,
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "updated_at": "2019-08-24T14:15:22Z",
  "user_created_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  "user_updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationMemberWithUserData](schemas.md#codersdkorganizationmemberwithuserdata) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Add organization member

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/members/{user} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations/{organization}/members/{user}`

### Parameters

| Name           | In   | Type   | Required | Description          |
|----------------|------|--------|----------|----------------------|
| `organization` | path | string | true     | Organization ID      |
| `user`         | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                               |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationMember](schemas.md#codersdkorganizationmember) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Remove organization member

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/organizations/{organization}/members/{user} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/organizations/{organization}/members/{user}`

### Parameters

| Name           | In   | Type   | Required | Description          |
|----------------|------|--------|----------|----------------------|
| `organization` | path | string | true     | Organization ID      |
| `user`         | path | string | true     | User ID, name, or me |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Assign role to organization member

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/organizations/{organization}/members/{user}/roles \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/organizations/{organization}/members/{user}/roles`

> Body parameter

```json
{
  "roles": [
    "string"
  ]
}
```

### Parameters

| Name           | In   | Type                                                   | Required | Description          |
|----------------|------|--------------------------------------------------------|----------|----------------------|
| `organization` | path | string                                                 | true     | Organization ID      |
| `user`         | path | string                                                 | true     | User ID, name, or me |
| `body`         | body | [codersdk.UpdateRoles](schemas.md#codersdkupdateroles) | true     | Update roles request |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                               |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OrganizationMember](schemas.md#codersdkorganizationmember) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Paginated organization members

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/paginated-members \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/paginated-members`

### Parameters

| Name           | In    | Type         | Required | Description                          |
|----------------|-------|--------------|----------|--------------------------------------|
| `organization` | path  | string       | true     | Organization ID                      |
| `q`            | query | string       | false    | Member search query                  |
| `after_id`     | query | string(uuid) | false    | After ID                             |
| `limit`        | query | integer      | false    | Page limit, if 0 returns all members |
| `offset`       | query | integer      | false    | Page offset                          |

### Example responses

> 200 Response

```json
[
  {
    "count": 0,
    "members": [
      {
        "avatar_url": "string",
        "created_at": "2019-08-24T14:15:22Z",
        "email": "string",
        "global_roles": [
          {
            "display_name": "string",
            "name": "string",
            "organization_id": "string"
          }
        ],
        "has_ai_seat": true,
        "is_service_account": true,
        "last_seen_at": "2019-08-24T14:15:22Z",
        "login_type": "",
        "name": "string",
        "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
        "roles": [
          {
            "display_name": "string",
            "name": "string",
            "organization_id": "string"
          }
        ],
        "status": "active",
        "updated_at": "2019-08-24T14:15:22Z",
        "user_created_at": "2019-08-24T14:15:22Z",
        "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
        "user_updated_at": "2019-08-24T14:15:22Z",
        "username": "string"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                    |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.PaginatedMembersResponse](schemas.md#codersdkpaginatedmembersresponse) |

<h3 id="paginated-organization-members-responseschema">Response Schema</h3>

Status Code **200**

| Name                    | Type                                                 | Required | Restrictions | Description                                                                                      |
|-------------------------|------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------|
| `[array item]`          | array                                                | false    |              |                                                                                                  |
| `» count`               | integer                                              | false    |              |                                                                                                  |
| `» members`             | array                                                | false    |              |                                                                                                  |
| `»» avatar_url`         | string                                               | false    |              |                                                                                                  |
| `»» created_at`         | string(date-time)                                    | false    |              |                                                                                                  |
| `»» email`              | string                                               | false    |              |                                                                                                  |
| `»» global_roles`       | array                                                | false    |              |                                                                                                  |
| `»»» display_name`      | string                                               | false    |              |                                                                                                  |
| `»»» name`              | string                                               | false    |              |                                                                                                  |
| `»»» organization_id`   | string                                               | false    |              |                                                                                                  |
| `»» has_ai_seat`        | boolean                                              | false    |              | Has ai seat intentionally omits omitempty so the API always includes the field, even when false. |
| `»» is_service_account` | boolean                                              | false    |              |                                                                                                  |
| `»» last_seen_at`       | string(date-time)                                    | false    |              |                                                                                                  |
| `»» login_type`         | [codersdk.LoginType](schemas.md#codersdklogintype)   | false    |              |                                                                                                  |
| `»» name`               | string                                               | false    |              |                                                                                                  |
| `»» organization_id`    | string(uuid)                                         | false    |              |                                                                                                  |
| `»» roles`              | array                                                | false    |              |                                                                                                  |
| `»» status`             | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false    |              |                                                                                                  |
| `»» updated_at`         | string(date-time)                                    | false    |              |                                                                                                  |
| `»» user_created_at`    | string(date-time)                                    | false    |              |                                                                                                  |
| `»» user_id`            | string(uuid)                                         | false    |              |                                                                                                  |
| `»» user_updated_at`    | string(date-time)                                    | false    |              |                                                                                                  |
| `»» username`           | string                                               | false    |              |                                                                                                  |

#### Enumerated Values

| Property     | Value(s)                                          |
|--------------|---------------------------------------------------|
| `login_type` | ``, `github`, `none`, `oidc`, `password`, `token` |
| `status`     | `active`, `suspended`                             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get site member roles

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/roles \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/roles`

### Example responses

> 200 Response

```json
[
  {
    "assignable": true,
    "built_in": true,
    "display_name": "string",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_member_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "organization_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "site_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ],
    "user_permissions": [
      {
        "action": "application_connect",
        "negate": true,
        "resource_type": "*"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                  |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.AssignableRoles](schemas.md#codersdkassignableroles) |

<h3 id="get-site-member-roles-responseschema">Response Schema</h3>

Status Code **200**

| Name                                | Type                                                     | Required | Restrictions | Description                                                                                            |
|-------------------------------------|----------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------|
| `[array item]`                      | array                                                    | false    |              |                                                                                                        |
| `» assignable`                      | boolean                                                  | false    |              |                                                                                                        |
| `» built_in`                        | boolean                                                  | false    |              | Built in roles are immutable                                                                           |
| `» display_name`                    | string                                                   | false    |              |                                                                                                        |
| `» name`                            | string                                                   | false    |              |                                                                                                        |
| `» organization_id`                 | string(uuid)                                             | false    |              |                                                                                                        |
| `» organization_member_permissions` | array                                                    | false    |              | Organization member permissions are specific for the organization in the field 'OrganizationID' above. |
| `»» action`                         | [codersdk.RBACAction](schemas.md#codersdkrbacaction)     | false    |              |                                                                                                        |
| `»» negate`                         | boolean                                                  | false    |              | Negate makes this a negative permission                                                                |
| `»» resource_type`                  | [codersdk.RBACResource](schemas.md#codersdkrbacresource) | false    |              |                                                                                                        |
| `» organization_permissions`        | array                                                    | false    |              | Organization permissions are specific for the organization in the field 'OrganizationID' above.        |
| `» site_permissions`                | array                                                    | false    |              |                                                                                                        |
| `» user_permissions`                | array                                                    | false    |              |                                                                                                        |

#### Enumerated Values

| Property        | Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action`        | `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `resource_type` | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `chat_model_config`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `mcp_server_config`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_build_orchestration`, `workspace_dormant`, `workspace_proxy` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Notifications

Source: https://coder.com/docs/reference/api/notifications

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Send a custom notification

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/notifications/custom \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/notifications/custom`

> Body parameter

```json
{
  "content": {
    "message": "string",
    "title": "string"
  }
}
```

### Parameters

| Name   | In   | Type                                                                               | Required | Description                          |
|--------|------|------------------------------------------------------------------------------------|----------|--------------------------------------|
| `body` | body | [codersdk.CustomNotificationRequest](schemas.md#codersdkcustomnotificationrequest) | true     | Provide a non-empty title or message |

### Example responses

> 400 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                                    | Description                                   | Schema                                           |
|--------|----------------------------------------------------------------------------|-----------------------------------------------|--------------------------------------------------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5)            | No Content                                    |                                                  |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)           | Invalid request body                          | [codersdk.Response](schemas.md#codersdkresponse) |
| 403    | [Forbidden](https://tools.ietf.org/html/rfc7231#section-6.5.3)             | System users cannot send custom notifications | [codersdk.Response](schemas.md#codersdkresponse) |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Failed to send custom notification            | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get notification dispatch methods

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/notifications/dispatch-methods \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/notifications/dispatch-methods`

### Example responses

> 200 Response

```json
[
  {
    "available": [
      "string"
    ],
    "default": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                          |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.NotificationMethodsResponse](schemas.md#codersdknotificationmethodsresponse) |

<h3 id="get-notification-dispatch-methods-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `[array item]` | array  | false    |              |             |
| `» available`  | array  | false    |              |             |
| `» default`    | string | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List inbox notifications

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/notifications/inbox \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/notifications/inbox`

### Parameters

| Name              | In    | Type         | Required | Description                                                                                                     |
|-------------------|-------|--------------|----------|-----------------------------------------------------------------------------------------------------------------|
| `targets`         | query | string       | false    | Comma-separated list of target IDs to filter notifications                                                      |
| `templates`       | query | string       | false    | Comma-separated list of template IDs to filter notifications                                                    |
| `read_status`     | query | string       | false    | Filter notifications by read status. Possible values: read, unread, all                                         |
| `starting_before` | query | string(uuid) | false    | ID of the last notification from the current page. Notifications returned will be older than the associated one |

### Example responses

> 200 Response

```json
{
  "notifications": [
    {
      "actions": [
        {
          "label": "string",
          "url": "string"
        }
      ],
      "content": "string",
      "created_at": "2019-08-24T14:15:22Z",
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "read_at": "string",
      "targets": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "title": "string",
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
    }
  ],
  "unread_count": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ListInboxNotificationsResponse](schemas.md#codersdklistinboxnotificationsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Mark all unread notifications as read

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/notifications/inbox/mark-all-as-read \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/notifications/inbox/mark-all-as-read`

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Watch for new inbox notifications

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/notifications/inbox/watch \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/notifications/inbox/watch`

### Parameters

| Name          | In    | Type   | Required | Description                                                             |
|---------------|-------|--------|----------|-------------------------------------------------------------------------|
| `targets`     | query | string | false    | Comma-separated list of target IDs to filter notifications              |
| `templates`   | query | string | false    | Comma-separated list of template IDs to filter notifications            |
| `read_status` | query | string | false    | Filter notifications by read status. Possible values: read, unread, all |
| `format`      | query | string | false    | Define the output format for notifications title and body.              |

#### Enumerated Values

| Parameter | Value(s)                |
|-----------|-------------------------|
| `format`  | `markdown`, `plaintext` |

### Example responses

> 200 Response

```json
{
  "notification": {
    "actions": [
      {
        "label": "string",
        "url": "string"
      }
    ],
    "content": "string",
    "created_at": "2019-08-24T14:15:22Z",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "read_at": "string",
    "targets": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
    "title": "string",
    "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
  },
  "unread_count": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GetInboxNotificationResponse](schemas.md#codersdkgetinboxnotificationresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update read status of a notification

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/notifications/inbox/{id}/read-status \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/notifications/inbox/{id}/read-status`

### Parameters

| Name | In   | Type   | Required | Description            |
|------|------|--------|----------|------------------------|
| `id` | path | string | true     | id of the notification |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get notifications settings

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/notifications/settings \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/notifications/settings`

### Example responses

> 200 Response

```json
{
  "notifier_paused": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                     |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.NotificationsSettings](schemas.md#codersdknotificationssettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update notifications settings

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/notifications/settings \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/notifications/settings`

> Body parameter

```json
{
  "notifier_paused": true
}
```

### Parameters

| Name   | In   | Type                                                                       | Required | Description                    |
|--------|------|----------------------------------------------------------------------------|----------|--------------------------------|
| `body` | body | [codersdk.NotificationsSettings](schemas.md#codersdknotificationssettings) | true     | Notifications settings request |

### Example responses

> 200 Response

```json
{
  "notifier_paused": true
}
```

### Responses

| Status | Meaning                                                         | Description  | Schema                                                                     |
|--------|-----------------------------------------------------------------|--------------|----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | OK           | [codersdk.NotificationsSettings](schemas.md#codersdknotificationssettings) |
| 304    | [Not Modified](https://tools.ietf.org/html/rfc7232#section-4.1) | Not Modified |                                                                            |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get custom notification templates

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/notifications/templates/custom \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/notifications/templates/custom`

### Example responses

> 200 Response

```json
[
  {
    "actions": "string",
    "body_template": "string",
    "enabled_by_default": true,
    "group": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "kind": "string",
    "method": "string",
    "name": "string",
    "title_template": "string"
  }
]
```

### Responses

| Status | Meaning                                                                    | Description                                        | Schema                                                                            |
|--------|----------------------------------------------------------------------------|----------------------------------------------------|-----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | OK                                                 | array of [codersdk.NotificationTemplate](schemas.md#codersdknotificationtemplate) |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Failed to retrieve 'custom' notifications template | [codersdk.Response](schemas.md#codersdkresponse)                                  |

<h3 id="get-custom-notification-templates-responseschema">Response Schema</h3>

Status Code **200**

| Name                   | Type         | Required | Restrictions | Description |
|------------------------|--------------|----------|--------------|-------------|
| `[array item]`         | array        | false    |              |             |
| `» actions`            | string       | false    |              |             |
| `» body_template`      | string       | false    |              |             |
| `» enabled_by_default` | boolean      | false    |              |             |
| `» group`              | string       | false    |              |             |
| `» id`                 | string(uuid) | false    |              |             |
| `» kind`               | string       | false    |              |             |
| `» method`             | string       | false    |              |             |
| `» name`               | string       | false    |              |             |
| `» title_template`     | string       | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get system notification templates

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/notifications/templates/system \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/notifications/templates/system`

### Example responses

> 200 Response

```json
[
  {
    "actions": "string",
    "body_template": "string",
    "enabled_by_default": true,
    "group": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "kind": "string",
    "method": "string",
    "name": "string",
    "title_template": "string"
  }
]
```

### Responses

| Status | Meaning                                                                    | Description                                        | Schema                                                                            |
|--------|----------------------------------------------------------------------------|----------------------------------------------------|-----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)                    | OK                                                 | array of [codersdk.NotificationTemplate](schemas.md#codersdknotificationtemplate) |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Failed to retrieve 'system' notifications template | [codersdk.Response](schemas.md#codersdkresponse)                                  |

<h3 id="get-system-notification-templates-responseschema">Response Schema</h3>

Status Code **200**

| Name                   | Type         | Required | Restrictions | Description |
|------------------------|--------------|----------|--------------|-------------|
| `[array item]`         | array        | false    |              |             |
| `» actions`            | string       | false    |              |             |
| `» body_template`      | string       | false    |              |             |
| `» enabled_by_default` | boolean      | false    |              |             |
| `» group`              | string       | false    |              |             |
| `» id`                 | string(uuid) | false    |              |             |
| `» kind`               | string       | false    |              |             |
| `» method`             | string       | false    |              |             |
| `» name`               | string       | false    |              |             |
| `» title_template`     | string       | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Send a test notification

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/notifications/test \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/notifications/test`

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user notification preferences

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/notifications/preferences \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/notifications/preferences`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
[
  {
    "disabled": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "updated_at": "2019-08-24T14:15:22Z"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.NotificationPreference](schemas.md#codersdknotificationpreference) |

<h3 id="get-user-notification-preferences-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type              | Required | Restrictions | Description |
|----------------|-------------------|----------|--------------|-------------|
| `[array item]` | array             | false    |              |             |
| `» disabled`   | boolean           | false    |              |             |
| `» id`         | string(uuid)      | false    |              |             |
| `» updated_at` | string(date-time) | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user notification preferences

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/notifications/preferences \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/notifications/preferences`

> Body parameter

```json
{
  "template_disabled_map": {
    "property1": true,
    "property2": true
  }
}
```

### Parameters

| Name   | In   | Type                                                                                               | Required | Description          |
|--------|------|----------------------------------------------------------------------------------------------------|----------|----------------------|
| `user` | path | string                                                                                             | true     | User ID, name, or me |
| `body` | body | [codersdk.UpdateUserNotificationPreferences](schemas.md#codersdkupdateusernotificationpreferences) | true     | Preferences          |

### Example responses

> 200 Response

```json
[
  {
    "disabled": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "updated_at": "2019-08-24T14:15:22Z"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.NotificationPreference](schemas.md#codersdknotificationpreference) |

<h3 id="update-user-notification-preferences-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type              | Required | Restrictions | Description |
|----------------|-------------------|----------|--------------|-------------|
| `[array item]` | array             | false    |              |             |
| `» disabled`   | boolean           | false    |              |             |
| `» id`         | string(uuid)      | false    |              |             |
| `» updated_at` | string(date-time) | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Organizations

Source: https://coder.com/docs/reference/api/organizations

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get organizations

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations`

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "default_org_member_roles": [
      "string"
    ],
    "description": "string",
    "display_name": "string",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "is_default": true,
    "name": "string",
    "updated_at": "2019-08-24T14:15:22Z"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                            |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Organization](schemas.md#codersdkorganization) |

<h3 id="get-organizations-responseschema">Response Schema</h3>

Status Code **200**

| Name                         | Type              | Required | Restrictions | Description                                                                                                                                     |
|------------------------------|-------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`               | array             | false    |              |                                                                                                                                                 |
| `» created_at`               | string(date-time) | true     |              |                                                                                                                                                 |
| `» default_org_member_roles` | array             | false    |              | Default org member roles are unioned into every member's effective roles at request time. Changes propagate to all members on the next request. |
| `» description`              | string            | false    |              |                                                                                                                                                 |
| `» display_name`             | string            | false    |              |                                                                                                                                                 |
| `» icon`                     | string            | false    |              |                                                                                                                                                 |
| `» id`                       | string(uuid)      | true     |              |                                                                                                                                                 |
| `» is_default`               | boolean           | true     |              |                                                                                                                                                 |
| `» name`                     | string            | false    |              |                                                                                                                                                 |
| `» updated_at`               | string(date-time) | true     |              |                                                                                                                                                 |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create organization

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations`

> Body parameter

```json
{
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "name": "string"
}
```

### Parameters

| Name   | In   | Type                                                                               | Required | Description                 |
|--------|------|------------------------------------------------------------------------------------|----------|-----------------------------|
| `body` | body | [codersdk.CreateOrganizationRequest](schemas.md#codersdkcreateorganizationrequest) | true     | Create organization request |

### Example responses

> 201 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "default_org_member_roles": [
    "string"
  ],
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_default": true,
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                   |
|--------|--------------------------------------------------------------|-------------|----------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.Organization](schemas.md#codersdkorganization) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get organization by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "default_org_member_roles": [
    "string"
  ],
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_default": true,
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Organization](schemas.md#codersdkorganization) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete organization

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/organizations/{organization} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/organizations/{organization}`

### Parameters

| Name           | In   | Type   | Required | Description             |
|----------------|------|--------|----------|-------------------------|
| `organization` | path | string | true     | Organization ID or name |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update organization

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/organizations/{organization} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/organizations/{organization}`

> Body parameter

```json
{
  "default_org_member_roles": [
    "string"
  ],
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "name": "string"
}
```

### Parameters

| Name           | In   | Type                                                                               | Required | Description                |
|----------------|------|------------------------------------------------------------------------------------|----------|----------------------------|
| `organization` | path | string                                                                             | true     | Organization ID or name    |
| `body`         | body | [codersdk.UpdateOrganizationRequest](schemas.md#codersdkupdateorganizationrequest) | true     | Patch organization request |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "default_org_member_roles": [
    "string"
  ],
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_default": true,
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Organization](schemas.md#codersdkorganization) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get provisioner jobs

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisionerjobs \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/provisionerjobs`

### Parameters

| Name           | In    | Type         | Required | Description                                                                          |
|----------------|-------|--------------|----------|--------------------------------------------------------------------------------------|
| `organization` | path  | string(uuid) | true     | Organization ID                                                                      |
| `limit`        | query | integer      | false    | Page limit                                                                           |
| `ids`          | query | array(uuid)  | false    | Filter results by job IDs                                                            |
| `status`       | query | string       | false    | Filter results by status                                                             |
| `tags`         | query | string       | false    | Provisioner tags to filter by (JSON of the form `{'tag1':'value1','tag2':'value2'}`) |
| `initiator`    | query | string(uuid) | false    | Filter results by initiator                                                          |

#### Enumerated Values

| Parameter | Value(s)                                                                        |
|-----------|---------------------------------------------------------------------------------|
| `status`  | `canceled`, `canceling`, `failed`, `pending`, `running`, `succeeded`, `unknown` |

### Example responses

> 200 Response

```json
[
  {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) |

<h3 id="get-provisioner-jobs-responseschema">Response Schema</h3>

Status Code **200**

| Name                            | Type                                                                         | Required | Restrictions | Description |
|---------------------------------|------------------------------------------------------------------------------|----------|--------------|-------------|
| `[array item]`                  | array                                                                        | false    |              |             |
| `» available_workers`           | array                                                                        | false    |              |             |
| `» canceled_at`                 | string(date-time)                                                            | false    |              |             |
| `» completed_at`                | string(date-time)                                                            | false    |              |             |
| `» created_at`                  | string(date-time)                                                            | false    |              |             |
| `» error`                       | string                                                                       | false    |              |             |
| `» error_code`                  | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode)                     | false    |              |             |
| `» file_id`                     | string(uuid)                                                                 | false    |              |             |
| `» id`                          | string(uuid)                                                                 | false    |              |             |
| `» initiator_id`                | string(uuid)                                                                 | false    |              |             |
| `» input`                       | [codersdk.ProvisionerJobInput](schemas.md#codersdkprovisionerjobinput)       | false    |              |             |
| `»» error`                      | string                                                                       | false    |              |             |
| `»» template_version_id`        | string(uuid)                                                                 | false    |              |             |
| `»» workspace_build_id`         | string(uuid)                                                                 | false    |              |             |
| `» logs_overflowed`             | boolean                                                                      | false    |              |             |
| `» metadata`                    | [codersdk.ProvisionerJobMetadata](schemas.md#codersdkprovisionerjobmetadata) | false    |              |             |
| `»» template_display_name`      | string                                                                       | false    |              |             |
| `»» template_icon`              | string                                                                       | false    |              |             |
| `»» template_id`                | string(uuid)                                                                 | false    |              |             |
| `»» template_name`              | string                                                                       | false    |              |             |
| `»» template_version_name`      | string                                                                       | false    |              |             |
| `»» workspace_build_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)       | false    |              |             |
| `»» workspace_id`               | string(uuid)                                                                 | false    |              |             |
| `»» workspace_name`             | string                                                                       | false    |              |             |
| `» organization_id`             | string(uuid)                                                                 | false    |              |             |
| `» queue_position`              | integer                                                                      | false    |              |             |
| `» queue_size`                  | integer                                                                      | false    |              |             |
| `» started_at`                  | string(date-time)                                                            | false    |              |             |
| `» status`                      | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus)     | false    |              |             |
| `» tags`                        | object                                                                       | false    |              |             |
| `»» [any property]`             | string                                                                       | false    |              |             |
| `» type`                        | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype)         | false    |              |             |
| `» worker_id`                   | string(uuid)                                                                 | false    |              |             |
| `» worker_name`                 | string                                                                       | false    |              |             |

#### Enumerated Values

| Property                     | Value(s)                                                                 |
|------------------------------|--------------------------------------------------------------------------|
| `error_code`                 | `INSUFFICIENT_QUOTA`, `REQUIRED_TEMPLATE_VARIABLES`                      |
| `workspace_build_transition` | `delete`, `start`, `stop`                                                |
| `status`                     | `canceled`, `canceling`, `failed`, `pending`, `running`, `succeeded`     |
| `type`                       | `template_version_dry_run`, `template_version_import`, `workspace_build` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get provisioner job

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisionerjobs/{job} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/provisionerjobs/{job}`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |
| `job`          | path | string(uuid) | true     | Job ID          |

### Example responses

> 200 Response

```json
{
  "available_workers": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "canceled_at": "2019-08-24T14:15:22Z",
  "completed_at": "2019-08-24T14:15:22Z",
  "created_at": "2019-08-24T14:15:22Z",
  "error": "string",
  "error_code": "REQUIRED_TEMPLATE_VARIABLES",
  "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "input": {
    "error": "string",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
  },
  "logs_overflowed": true,
  "metadata": {
    "template_display_name": "string",
    "template_icon": "string",
    "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
    "template_name": "string",
    "template_version_name": "string",
    "workspace_build_transition": "start",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string"
  },
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "queue_position": 0,
  "queue_size": 0,
  "started_at": "2019-08-24T14:15:22Z",
  "status": "pending",
  "tags": {
    "property1": "string",
    "property2": "string"
  },
  "type": "template_version_import",
  "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
  "worker_name": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# PortSharing

Source: https://coder.com/docs/reference/api/portsharing

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get workspace agent port shares

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/port-share \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/port-share`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Example responses

> 200 Response

```json
{
  "shares": [
    {
      "agent_name": "string",
      "port": 0,
      "protocol": "http",
      "share_level": "owner",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceAgentPortShares](schemas.md#codersdkworkspaceagentportshares) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Upsert workspace agent port share

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/port-share \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaces/{workspace}/port-share`

> Body parameter

```json
{
  "agent_name": "string",
  "port": 0,
  "protocol": "http",
  "share_level": "owner"
}
```

### Parameters

| Name        | In   | Type                                                                                                     | Required | Description                       |
|-------------|------|----------------------------------------------------------------------------------------------------------|----------|-----------------------------------|
| `workspace` | path | string(uuid)                                                                                             | true     | Workspace ID                      |
| `body`      | body | [codersdk.UpsertWorkspaceAgentPortShareRequest](schemas.md#codersdkupsertworkspaceagentportsharerequest) | true     | Upsert port sharing level request |

### Example responses

> 200 Response

```json
{
  "agent_name": "string",
  "port": 0,
  "protocol": "http",
  "share_level": "owner",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                         |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceAgentPortShare](schemas.md#codersdkworkspaceagentportshare) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete workspace agent port share

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/workspaces/{workspace}/port-share \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/workspaces/{workspace}/port-share`

> Body parameter

```json
{
  "agent_name": "string",
  "port": 0
}
```

### Parameters

| Name        | In   | Type                                                                                                     | Required | Description                       |
|-------------|------|----------------------------------------------------------------------------------------------------------|----------|-----------------------------------|
| `workspace` | path | string(uuid)                                                                                             | true     | Workspace ID                      |
| `body`      | body | [codersdk.DeleteWorkspaceAgentPortShareRequest](schemas.md#codersdkdeleteworkspaceagentportsharerequest) | true     | Delete port sharing level request |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Prebuilds

Source: https://coder.com/docs/reference/api/prebuilds

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get prebuilds settings

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/prebuilds/settings \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/prebuilds/settings`

### Example responses

> 200 Response

```json
{
  "reconciliation_paused": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                             |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.PrebuildsSettings](schemas.md#codersdkprebuildssettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update prebuilds settings

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/prebuilds/settings \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/prebuilds/settings`

> Body parameter

```json
{
  "reconciliation_paused": true
}
```

### Parameters

| Name   | In   | Type                                                               | Required | Description                |
|--------|------|--------------------------------------------------------------------|----------|----------------------------|
| `body` | body | [codersdk.PrebuildsSettings](schemas.md#codersdkprebuildssettings) | true     | Prebuilds settings request |

### Example responses

> 200 Response

```json
{
  "reconciliation_paused": true
}
```

### Responses

| Status | Meaning                                                         | Description  | Schema                                                             |
|--------|-----------------------------------------------------------------|--------------|--------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | OK           | [codersdk.PrebuildsSettings](schemas.md#codersdkprebuildssettings) |
| 304    | [Not Modified](https://tools.ietf.org/html/rfc7232#section-4.1) | Not Modified |                                                                    |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Provisioning

Source: https://coder.com/docs/reference/api/provisioning

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get provisioner daemons

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/provisionerdaemons \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/provisionerdaemons`

### Parameters

| Name           | In    | Type         | Required | Description                                                                          |
|----------------|-------|--------------|----------|--------------------------------------------------------------------------------------|
| `organization` | path  | string(uuid) | true     | Organization ID                                                                      |
| `limit`        | query | integer      | false    | Page limit                                                                           |
| `ids`          | query | array(uuid)  | false    | Filter results by job IDs                                                            |
| `status`       | query | string       | false    | Filter results by status                                                             |
| `tags`         | query | string       | false    | Provisioner tags to filter by (JSON of the form `{'tag1':'value1','tag2':'value2'}`) |

#### Enumerated Values

| Parameter | Value(s)                                                                        |
|-----------|---------------------------------------------------------------------------------|
| `status`  | `canceled`, `canceling`, `failed`, `pending`, `running`, `succeeded`, `unknown` |

### Example responses

> 200 Response

```json
[
  {
    "api_version": "string",
    "created_at": "2019-08-24T14:15:22Z",
    "current_job": {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "status": "pending",
      "template_display_name": "string",
      "template_icon": "string",
      "template_name": "string"
    },
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
    "key_name": "string",
    "last_seen_at": "2019-08-24T14:15:22Z",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "previous_job": {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "status": "pending",
      "template_display_name": "string",
      "template_icon": "string",
      "template_name": "string"
    },
    "provisioners": [
      "string"
    ],
    "status": "offline",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "version": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ProvisionerDaemon](schemas.md#codersdkprovisionerdaemon) |

<h3 id="get-provisioner-daemons-responseschema">Response Schema</h3>

Status Code **200**

| Name                       | Type                                                                           | Required | Restrictions | Description      |
|----------------------------|--------------------------------------------------------------------------------|----------|--------------|------------------|
| `[array item]`             | array                                                                          | false    |              |                  |
| `» api_version`            | string                                                                         | false    |              |                  |
| `» created_at`             | string(date-time)                                                              | false    |              |                  |
| `» current_job`            | [codersdk.ProvisionerDaemonJob](schemas.md#codersdkprovisionerdaemonjob)       | false    |              |                  |
| `»» id`                    | string(uuid)                                                                   | false    |              |                  |
| `»» status`                | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus)       | false    |              |                  |
| `»» template_display_name` | string                                                                         | false    |              |                  |
| `»» template_icon`         | string                                                                         | false    |              |                  |
| `»» template_name`         | string                                                                         | false    |              |                  |
| `» id`                     | string(uuid)                                                                   | false    |              |                  |
| `» key_id`                 | string(uuid)                                                                   | false    |              |                  |
| `» key_name`               | string                                                                         | false    |              | Optional fields. |
| `» last_seen_at`           | string(date-time)                                                              | false    |              |                  |
| `» name`                   | string                                                                         | false    |              |                  |
| `» organization_id`        | string(uuid)                                                                   | false    |              |                  |
| `» previous_job`           | [codersdk.ProvisionerDaemonJob](schemas.md#codersdkprovisionerdaemonjob)       | false    |              |                  |
| `» provisioners`           | array                                                                          | false    |              |                  |
| `» status`                 | [codersdk.ProvisionerDaemonStatus](schemas.md#codersdkprovisionerdaemonstatus) | false    |              |                  |
| `» tags`                   | object                                                                         | false    |              |                  |
| `»» [any property]`        | string                                                                         | false    |              |                  |
| `» version`                | string                                                                         | false    |              |                  |

#### Enumerated Values

| Property | Value(s)                                                                                        |
|----------|-------------------------------------------------------------------------------------------------|
| `status` | `busy`, `canceled`, `canceling`, `failed`, `idle`, `offline`, `pending`, `running`, `succeeded` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Schemas

Source: https://coder.com/docs/reference/api/schemas

<!-- DO NOT EDIT | GENERATED CONTENT -->

## agentsdk.AWSInstanceIdentityToken

```json
{
  "agent_name": "string",
  "document": "string",
  "signature": "string"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description                                                                                                                                      |
|--------------|--------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_name` | string | false    |              | Agent name optionally selects a specific agent when multiple agents share the same instance identity. An empty string is treated as unspecified. |
| `document`   | string | true     |              |                                                                                                                                                  |
| `signature`  | string | true     |              |                                                                                                                                                  |

## agentsdk.AuthenticateResponse

```json
{
  "session_token": "string"
}
```

### Properties

| Name            | Type   | Required | Restrictions | Description |
|-----------------|--------|----------|--------------|-------------|
| `session_token` | string | false    |              |             |

## agentsdk.AzureInstanceIdentityToken

```json
{
  "agent_name": "string",
  "encoding": "string",
  "signature": "string"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description                                                                                                                                      |
|--------------|--------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_name` | string | false    |              | Agent name optionally selects a specific agent when multiple agents share the same instance identity. An empty string is treated as unspecified. |
| `encoding`   | string | true     |              |                                                                                                                                                  |
| `signature`  | string | true     |              |                                                                                                                                                  |

## agentsdk.ExternalAuthResponse

```json
{
  "access_token": "string",
  "expires_at": "string",
  "password": "string",
  "token_extra": {},
  "type": "string",
  "url": "string",
  "username": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description                                                                                                                    |
|----------------|--------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------|
| `access_token` | string | false    |              |                                                                                                                                |
| `expires_at`   | string | false    |              | Expires at is the time the token expires, normalized to UTC (for example, "2024-06-01T15:04:05Z"). Zero value means no expiry. |
| `password`     | string | false    |              |                                                                                                                                |
| `token_extra`  | object | false    |              |                                                                                                                                |
| `type`         | string | false    |              |                                                                                                                                |
| `url`          | string | false    |              |                                                                                                                                |
| `username`     | string | false    |              | Deprecated: Only supported on `/workspaceagents/me/gitauth` for backwards compatibility.                                       |

## agentsdk.GitSSHKey

```json
{
  "private_key": "string",
  "public_key": "string"
}
```

### Properties

| Name          | Type   | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `private_key` | string | false    |              |             |
| `public_key`  | string | false    |              |             |

## agentsdk.GoogleInstanceIdentityToken

```json
{
  "agent_name": "string",
  "json_web_token": "string"
}
```

### Properties

| Name             | Type   | Required | Restrictions | Description                                                                                                                                      |
|------------------|--------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_name`     | string | false    |              | Agent name optionally selects a specific agent when multiple agents share the same instance identity. An empty string is treated as unspecified. |
| `json_web_token` | string | true     |              |                                                                                                                                                  |

## agentsdk.Log

```json
{
  "created_at": "string",
  "level": "trace",
  "output": "string"
}
```

### Properties

| Name         | Type                                   | Required | Restrictions | Description |
|--------------|----------------------------------------|----------|--------------|-------------|
| `created_at` | string                                 | false    |              |             |
| `level`      | [codersdk.LogLevel](#codersdkloglevel) | false    |              |             |
| `output`     | string                                 | false    |              |             |

## agentsdk.PatchAppStatus

```json
{
  "app_slug": "string",
  "icon": "string",
  "message": "string",
  "needs_user_attention": true,
  "state": "working",
  "uri": "string"
}
```

### Properties

| Name                   | Type                                                                 | Required | Restrictions | Description                                                               |
|------------------------|----------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------|
| `app_slug`             | string                                                               | false    |              |                                                                           |
| `icon`                 | string                                                               | false    |              | Deprecated: this field is unused and will be removed in a future version. |
| `message`              | string                                                               | false    |              |                                                                           |
| `needs_user_attention` | boolean                                                              | false    |              | Deprecated: this field is unused and will be removed in a future version. |
| `state`                | [codersdk.WorkspaceAppStatusState](#codersdkworkspaceappstatusstate) | false    |              |                                                                           |
| `uri`                  | string                                                               | false    |              |                                                                           |

## agentsdk.PatchLogs

```json
{
  "log_source_id": "string",
  "logs": [
    {
      "created_at": "string",
      "level": "trace",
      "output": "string"
    }
  ]
}
```

### Properties

| Name            | Type                                  | Required | Restrictions | Description |
|-----------------|---------------------------------------|----------|--------------|-------------|
| `log_source_id` | string                                | false    |              |             |
| `logs`          | array of [agentsdk.Log](#agentsdklog) | false    |              |             |

## agentsdk.PostLogSourceRequest

```json
{
  "display_name": "string",
  "icon": "string",
  "id": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description                                                                                                                                                                                    |
|----------------|--------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `display_name` | string | false    |              |                                                                                                                                                                                                |
| `icon`         | string | false    |              |                                                                                                                                                                                                |
| `id`           | string | false    |              | ID is a unique identifier for the log source. It is scoped to a workspace agent, and can be statically defined inside code to prevent duplicate sources from being created for the same agent. |

## agentsdk.ReinitializationEvent

```json
{
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "reason": "prebuild_claimed",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Properties

| Name           | Type                                                               | Required | Restrictions | Description |
|----------------|--------------------------------------------------------------------|----------|--------------|-------------|
| `owner_id`     | string                                                             | false    |              |             |
| `reason`       | [agentsdk.ReinitializationReason](#agentsdkreinitializationreason) | false    |              |             |
| `workspace_id` | string                                                             | false    |              |             |

## agentsdk.ReinitializationReason

```json
"prebuild_claimed"
```

### Properties

#### Enumerated Values

| Value(s)           |
|--------------------|
| `prebuild_claimed` |

## coderd.chatsByWorkspaceResponse

```json
{
  "property1": "string",
  "property2": "string"
}
```

### Properties

| Name             | Type   | Required | Restrictions | Description |
|------------------|--------|----------|--------------|-------------|
| `[any property]` | string | false    |              |             |

## coderd.cspViolation

```json
{
  "csp-report": {}
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description |
|--------------|--------|----------|--------------|-------------|
| `csp-report` | object | false    |              |             |

## codersdk.ACLAvailable

```json
{
  "groups": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "members": [
        {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        }
      ],
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "source": "user",
      "total_member_count": 0
    }
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Properties

| Name     | Type                                                  | Required | Restrictions | Description |
|----------|-------------------------------------------------------|----------|--------------|-------------|
| `groups` | array of [codersdk.Group](#codersdkgroup)             | false    |              |             |
| `users`  | array of [codersdk.ReducedUser](#codersdkreduceduser) | false    |              |             |

## codersdk.AIBridgeAgenticAction

```json
{
  "attribution": {
    "property1": "string",
    "property2": "string"
  },
  "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
  "model": "string",
  "thinking": [
    {
      "text": "string"
    }
  ],
  "token_usage": {
    "cache_read_input_tokens": 0,
    "cache_write_input_tokens": 0,
    "input_tokens": 0,
    "metadata": {
      "property1": null,
      "property2": null
    },
    "output_tokens": 0
  },
  "tool_calls": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "injected": true,
      "input": "string",
      "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
      "metadata": {
        "property1": null,
        "property2": null
      },
      "provider_response_id": "string",
      "server_url": "string",
      "tool": "string"
    }
  ]
}
```

### Properties

| Name              | Type                                                                                   | Required | Restrictions | Description                                                                                                         |
|-------------------|----------------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------|
| `attribution`     | [codersdk.AIBridgeAttribution](#codersdkaibridgeattribution)                           | false    |              | Attribution contains attribution data from this interception. Unknown attribution is serialized as an empty object. |
| `interception_id` | string                                                                                 | false    |              |                                                                                                                     |
| `model`           | string                                                                                 | false    |              |                                                                                                                     |
| `thinking`        | array of [codersdk.AIBridgeModelThought](#codersdkaibridgemodelthought)                | false    |              |                                                                                                                     |
| `token_usage`     | [codersdk.AIBridgeSessionThreadsTokenUsage](#codersdkaibridgesessionthreadstokenusage) | false    |              |                                                                                                                     |
| `tool_calls`      | array of [codersdk.AIBridgeToolCall](#codersdkaibridgetoolcall)                        | false    |              |                                                                                                                     |

## codersdk.AIBridgeAttribution

```json
{
  "property1": "string",
  "property2": "string"
}
```

### Properties

| Name             | Type   | Required | Restrictions | Description |
|------------------|--------|----------|--------------|-------------|
| `[any property]` | string | false    |              |             |

## codersdk.AIBridgeConfig

```json
{
  "actor_header_email": "string",
  "actor_header_id": "string",
  "actor_header_username": "string",
  "allow_byok": true,
  "api_dump_dir": "string",
  "budget_period": "string",
  "budget_policy": "string",
  "circuit_breaker_enabled": true,
  "circuit_breaker_failure_threshold": 0,
  "circuit_breaker_interval": 0,
  "circuit_breaker_max_requests": 0,
  "circuit_breaker_timeout": 0,
  "disable_content_recording": true,
  "enabled": true,
  "inject_coder_mcp_tools": true,
  "max_concurrency": 0,
  "rate_limit": 0,
  "retention": 0,
  "send_actor_headers": true,
  "structured_logging": true,
  "structured_logging_source": "string"
}
```

### Properties

| Name                                | Type    | Required | Restrictions | Description                                                                                                                                                                                                                                                            |
|-------------------------------------|---------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `actor_header_email`                | string  | false    |              |                                                                                                                                                                                                                                                                        |
| `actor_header_id`                   | string  | false    |              |                                                                                                                                                                                                                                                                        |
| `actor_header_username`             | string  | false    |              |                                                                                                                                                                                                                                                                        |
| `allow_byok`                        | boolean | false    |              |                                                                                                                                                                                                                                                                        |
| `api_dump_dir`                      | string  | false    |              | Api dump dir is the base directory under which each provider's request/response dumps are written, in a subdirectory named after the provider. Empty disables dumping.                                                                                                 |
| `budget_period`                     | string  | false    |              |                                                                                                                                                                                                                                                                        |
| `budget_policy`                     | string  | false    |              | Budget settings for AI Governance cost controls.                                                                                                                                                                                                                       |
| `circuit_breaker_enabled`           | boolean | false    |              | Circuit breaker protects against cascading failures from upstream AI provider overload (503, 529).                                                                                                                                                                     |
| `circuit_breaker_failure_threshold` | integer | false    |              |                                                                                                                                                                                                                                                                        |
| `circuit_breaker_interval`          | integer | false    |              |                                                                                                                                                                                                                                                                        |
| `circuit_breaker_max_requests`      | integer | false    |              |                                                                                                                                                                                                                                                                        |
| `circuit_breaker_timeout`           | integer | false    |              |                                                                                                                                                                                                                                                                        |
| `disable_content_recording`         | boolean | false    |              | Disable content recording stops user prompts, tool calls and model reasoning from being recorded, including tool names and their arguments. Interceptions and token usage are still recorded, so cost controls, budget enforcement and spend reporting are unaffected. |
| `enabled`                           | boolean | false    |              |                                                                                                                                                                                                                                                                        |
| `inject_coder_mcp_tools`            | boolean | false    |              | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release.                                                                                                                                                                           |
| `max_concurrency`                   | integer | false    |              |                                                                                                                                                                                                                                                                        |
| `rate_limit`                        | integer | false    |              |                                                                                                                                                                                                                                                                        |
| `retention`                         | integer | false    |              |                                                                                                                                                                                                                                                                        |
| `send_actor_headers`                | boolean | false    |              |                                                                                                                                                                                                                                                                        |
| `structured_logging`                | boolean | false    |              |                                                                                                                                                                                                                                                                        |
| `structured_logging_source`         | string  | false    |              | Structured logging source selects which process emits the records that StructuredLogging enables. See AIStructuredLoggingSource.                                                                                                                                       |

## codersdk.AIBridgeListSessionsResponse

```json
{
  "count": 0,
  "sessions": [
    {
      "client": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "id": "string",
      "initiator": {
        "avatar_url": "http://example.com",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string",
        "username": "string"
      },
      "last_active_at": "2019-08-24T14:15:22Z",
      "last_prompt": "string",
      "metadata": {
        "property1": null,
        "property2": null
      },
      "models": [
        "string"
      ],
      "network_calls": {
        "blocked": 0,
        "total": 0
      },
      "providers": [
        "string"
      ],
      "started_at": "2019-08-24T14:15:22Z",
      "threads": 0,
      "token_usage_summary": {
        "cache_read_input_tokens": 0,
        "cache_write_input_tokens": 0,
        "input_tokens": 0,
        "output_tokens": 0
      }
    }
  ]
}
```

### Properties

| Name       | Type                                                          | Required | Restrictions | Description |
|------------|---------------------------------------------------------------|----------|--------------|-------------|
| `count`    | integer                                                       | false    |              |             |
| `sessions` | array of [codersdk.AIBridgeSession](#codersdkaibridgesession) | false    |              |             |

## codersdk.AIBridgeModelThought

```json
{
  "text": "string"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description |
|--------|--------|----------|--------------|-------------|
| `text` | string | false    |              |             |

## codersdk.AIBridgeProvider

```json
{
  "display_name": "string",
  "icon": "string",
  "name": "string",
  "type": "openai"
}
```

### Properties

| Name           | Type                                               | Required | Restrictions | Description |
|----------------|----------------------------------------------------|----------|--------------|-------------|
| `display_name` | string                                             | false    |              |             |
| `icon`         | string                                             | false    |              |             |
| `name`         | string                                             | false    |              |             |
| `type`         | [codersdk.AIProviderType](#codersdkaiprovidertype) | false    |              |             |

## codersdk.AIBridgeProxyConfig

```json
{
  "allowed_private_cidrs": [
    "string"
  ],
  "api_dump_dir": "string",
  "cert_file": "string",
  "domain_allowlist": [
    "string"
  ],
  "enabled": true,
  "key_file": "string",
  "listen_addr": "string",
  "target": "string",
  "tls_cert_file": "string",
  "tls_key_file": "string",
  "upstream_proxy": "string",
  "upstream_proxy_ca": "string"
}
```

### Properties

| Name                    | Type            | Required | Restrictions | Description |
|-------------------------|-----------------|----------|--------------|-------------|
| `allowed_private_cidrs` | array of string | false    |              |             |
| `api_dump_dir`          | string          | false    |              |             |
| `cert_file`             | string          | false    |              |             |
| `domain_allowlist`      | array of string | false    |              |             |
| `enabled`               | boolean         | false    |              |             |
| `key_file`              | string          | false    |              |             |
| `listen_addr`           | string          | false    |              |             |
| `target`                | string          | false    |              |             |
| `tls_cert_file`         | string          | false    |              |             |
| `tls_key_file`          | string          | false    |              |             |
| `upstream_proxy`        | string          | false    |              |             |
| `upstream_proxy_ca`     | string          | false    |              |             |

## codersdk.AIBridgeSession

```json
{
  "client": "string",
  "ended_at": "2019-08-24T14:15:22Z",
  "id": "string",
  "initiator": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "last_active_at": "2019-08-24T14:15:22Z",
  "last_prompt": "string",
  "metadata": {
    "property1": null,
    "property2": null
  },
  "models": [
    "string"
  ],
  "network_calls": {
    "blocked": 0,
    "total": 0
  },
  "providers": [
    "string"
  ],
  "started_at": "2019-08-24T14:15:22Z",
  "threads": 0,
  "token_usage_summary": {
    "cache_read_input_tokens": 0,
    "cache_write_input_tokens": 0,
    "input_tokens": 0,
    "output_tokens": 0
  }
}
```

### Properties

| Name                  | Type                                                                                     | Required | Restrictions | Description                                                                                                                                                                                                                              |
|-----------------------|------------------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `client`              | string                                                                                   | false    |              |                                                                                                                                                                                                                                          |
| `ended_at`            | string                                                                                   | false    |              |                                                                                                                                                                                                                                          |
| `id`                  | string                                                                                   | false    |              |                                                                                                                                                                                                                                          |
| `initiator`           | [codersdk.MinimalUser](#codersdkminimaluser)                                             | false    |              |                                                                                                                                                                                                                                          |
| `last_active_at`      | string                                                                                   | false    |              |                                                                                                                                                                                                                                          |
| `last_prompt`         | string                                                                                   | false    |              |                                                                                                                                                                                                                                          |
| `metadata`            | object                                                                                   | false    |              |                                                                                                                                                                                                                                          |
| » `[any property]`    | any                                                                                      | false    |              |                                                                                                                                                                                                                                          |
| `models`              | array of string                                                                          | false    |              |                                                                                                                                                                                                                                          |
| `network_calls`       | [codersdk.AIBridgeSessionNetworkCallSummary](#codersdkaibridgesessionnetworkcallsummary) | false    |              | Network calls summarizes the Agent Firewall network requests made during the session. A nil value means the session did not pass through Agent Firewall, so network call monitoring was not active, which the UI surfaces as "Disabled". |
| `providers`           | array of string                                                                          | false    |              |                                                                                                                                                                                                                                          |
| `started_at`          | string                                                                                   | false    |              |                                                                                                                                                                                                                                          |
| `threads`             | integer                                                                                  | false    |              |                                                                                                                                                                                                                                          |
| `token_usage_summary` | [codersdk.AIBridgeSessionTokenUsageSummary](#codersdkaibridgesessiontokenusagesummary)   | false    |              |                                                                                                                                                                                                                                          |

## codersdk.AIBridgeSessionNetworkCallSummary

```json
{
  "blocked": 0,
  "total": 0
}
```

### Properties

| Name      | Type    | Required | Restrictions | Description |
|-----------|---------|----------|--------------|-------------|
| `blocked` | integer | false    |              |             |
| `total`   | integer | false    |              |             |

## codersdk.AIBridgeSessionNetworkDomain

```json
{
  "count": 0,
  "domain": "string"
}
```

### Properties

| Name     | Type    | Required | Restrictions | Description |
|----------|---------|----------|--------------|-------------|
| `count`  | integer | false    |              |             |
| `domain` | string  | false    |              |             |

## codersdk.AIBridgeSessionThreadsResponse

```json
{
  "client": "string",
  "ended_at": "2019-08-24T14:15:22Z",
  "id": "string",
  "initiator": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "metadata": {
    "property1": null,
    "property2": null
  },
  "models": [
    "string"
  ],
  "network_call_logs": [
    {
      "allowed": true,
      "captured_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "detail": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "matched_rule": "string",
      "method": "string",
      "proto": "string",
      "sequence_number": 0,
      "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82"
    }
  ],
  "network_calls": {
    "blocked": 0,
    "total": 0
  },
  "network_domain_count": 0,
  "network_top_domains": [
    {
      "count": 0,
      "domain": "string"
    }
  ],
  "page_ended_at": "2019-08-24T14:15:22Z",
  "page_started_at": "2019-08-24T14:15:22Z",
  "providers": [
    "string"
  ],
  "started_at": "2019-08-24T14:15:22Z",
  "threads": [
    {
      "agent_firewall_sequence_number": 0,
      "agent_firewall_session_id": "3735294f-18b1-4e7a-a269-99c30f0b30e7",
      "agentic_actions": [
        {
          "attribution": {
            "property1": "string",
            "property2": "string"
          },
          "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
          "model": "string",
          "thinking": [
            {
              "text": "string"
            }
          ],
          "token_usage": {
            "cache_read_input_tokens": 0,
            "cache_write_input_tokens": 0,
            "input_tokens": 0,
            "metadata": {
              "property1": null,
              "property2": null
            },
            "output_tokens": 0
          },
          "tool_calls": [
            {
              "created_at": "2019-08-24T14:15:22Z",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "injected": true,
              "input": "string",
              "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
              "metadata": {
                "property1": null,
                "property2": null
              },
              "provider_response_id": "string",
              "server_url": "string",
              "tool": "string"
            }
          ]
        }
      ],
      "attribution": {
        "property1": "string",
        "property2": "string"
      },
      "credential_hint": "string",
      "credential_kind": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "error_message": "string",
      "error_type": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "model": "string",
      "prompt": "string",
      "provider": "string",
      "started_at": "2019-08-24T14:15:22Z",
      "token_usage": {
        "cache_read_input_tokens": 0,
        "cache_write_input_tokens": 0,
        "input_tokens": 0,
        "metadata": {
          "property1": null,
          "property2": null
        },
        "output_tokens": 0
      }
    }
  ],
  "token_usage_summary": {
    "cache_read_input_tokens": 0,
    "cache_write_input_tokens": 0,
    "input_tokens": 0,
    "metadata": {
      "property1": null,
      "property2": null
    },
    "output_tokens": 0
  }
}
```

### Properties

| Name                   | Type                                                                                     | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                           |
|------------------------|------------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `client`               | string                                                                                   | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `ended_at`             | string                                                                                   | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `id`                   | string                                                                                   | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `initiator`            | [codersdk.MinimalUser](#codersdkminimaluser)                                             | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `metadata`             | object                                                                                   | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| » `[any property]`     | any                                                                                      | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `models`               | array of string                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `network_call_logs`    | array of [codersdk.AgentFirewallLog](#codersdkagentfirewalllog)                          | false    |              | Network call logs is the chronological list of individual network calls made during the session, holding the earliest calls up to a server-side cap. NetworkCalls remains authoritative for whole-session totals, so a shorter list than NetworkCalls.Total means the list was truncated. Empty when the session did not pass through Agent Firewall. |
| `network_calls`        | [codersdk.AIBridgeSessionNetworkCallSummary](#codersdkaibridgesessionnetworkcallsummary) | false    |              | Network calls summarizes the Agent Firewall network calls made during the session. A nil value means the session did not pass through Agent Firewall, so network call monitoring was not active, which the UI surfaces as "Disabled".                                                                                                                 |
| `network_domain_count` | integer                                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `network_top_domains`  | array of [codersdk.AIBridgeSessionNetworkDomain](#codersdkaibridgesessionnetworkdomain)  | false    |              | Network top domains lists the most contacted destination hosts, ordered by call count descending. NetworkDomainCount is the total number of distinct domains, used to render a "+N more" overflow beyond the listed domains.                                                                                                                          |
| `page_ended_at`        | string                                                                                   | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `page_started_at`      | string                                                                                   | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `providers`            | array of string                                                                          | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `started_at`           | string                                                                                   | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `threads`              | array of [codersdk.AIBridgeThread](#codersdkaibridgethread)                              | false    |              |                                                                                                                                                                                                                                                                                                                                                       |
| `token_usage_summary`  | [codersdk.AIBridgeSessionThreadsTokenUsage](#codersdkaibridgesessionthreadstokenusage)   | false    |              |                                                                                                                                                                                                                                                                                                                                                       |

## codersdk.AIBridgeSessionThreadsTokenUsage

```json
{
  "cache_read_input_tokens": 0,
  "cache_write_input_tokens": 0,
  "input_tokens": 0,
  "metadata": {
    "property1": null,
    "property2": null
  },
  "output_tokens": 0
}
```

### Properties

| Name                       | Type    | Required | Restrictions | Description |
|----------------------------|---------|----------|--------------|-------------|
| `cache_read_input_tokens`  | integer | false    |              |             |
| `cache_write_input_tokens` | integer | false    |              |             |
| `input_tokens`             | integer | false    |              |             |
| `metadata`                 | object  | false    |              |             |
| » `[any property]`         | any     | false    |              |             |
| `output_tokens`            | integer | false    |              |             |

## codersdk.AIBridgeSessionTokenUsageSummary

```json
{
  "cache_read_input_tokens": 0,
  "cache_write_input_tokens": 0,
  "input_tokens": 0,
  "output_tokens": 0
}
```

### Properties

| Name                       | Type    | Required | Restrictions | Description |
|----------------------------|---------|----------|--------------|-------------|
| `cache_read_input_tokens`  | integer | false    |              |             |
| `cache_write_input_tokens` | integer | false    |              |             |
| `input_tokens`             | integer | false    |              |             |
| `output_tokens`            | integer | false    |              |             |

## codersdk.AIBridgeThread

```json
{
  "agent_firewall_sequence_number": 0,
  "agent_firewall_session_id": "3735294f-18b1-4e7a-a269-99c30f0b30e7",
  "agentic_actions": [
    {
      "attribution": {
        "property1": "string",
        "property2": "string"
      },
      "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
      "model": "string",
      "thinking": [
        {
          "text": "string"
        }
      ],
      "token_usage": {
        "cache_read_input_tokens": 0,
        "cache_write_input_tokens": 0,
        "input_tokens": 0,
        "metadata": {
          "property1": null,
          "property2": null
        },
        "output_tokens": 0
      },
      "tool_calls": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "injected": true,
          "input": "string",
          "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
          "metadata": {
            "property1": null,
            "property2": null
          },
          "provider_response_id": "string",
          "server_url": "string",
          "tool": "string"
        }
      ]
    }
  ],
  "attribution": {
    "property1": "string",
    "property2": "string"
  },
  "credential_hint": "string",
  "credential_kind": "string",
  "ended_at": "2019-08-24T14:15:22Z",
  "error_message": "string",
  "error_type": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "model": "string",
  "prompt": "string",
  "provider": "string",
  "started_at": "2019-08-24T14:15:22Z",
  "token_usage": {
    "cache_read_input_tokens": 0,
    "cache_write_input_tokens": 0,
    "input_tokens": 0,
    "metadata": {
      "property1": null,
      "property2": null
    },
    "output_tokens": 0
  }
}
```

### Properties

| Name                             | Type                                                                                   | Required | Restrictions | Description                                                                                                                                                                                                                               |
|----------------------------------|----------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_firewall_sequence_number` | integer                                                                                | false    |              | Agent firewall sequence number is the firewall sequence number from the root interception. Used to determine the position of this LLM request in the firewall event stream. Nil when the request did not pass through the agent firewall. |
| `agent_firewall_session_id`      | string                                                                                 | false    |              | Agent firewall session ID links this thread to an agent firewall confinement session. Nil when the request did not pass through the agent firewall.                                                                                       |
| `agentic_actions`                | array of [codersdk.AIBridgeAgenticAction](#codersdkaibridgeagenticaction)              | false    |              |                                                                                                                                                                                                                                           |
| `attribution`                    | [codersdk.AIBridgeAttribution](#codersdkaibridgeattribution)                           | false    |              | Attribution contains attribution data from the root interception. Unknown attribution is serialized as an empty object.                                                                                                                   |
| `credential_hint`                | string                                                                                 | false    |              |                                                                                                                                                                                                                                           |
| `credential_kind`                | string                                                                                 | false    |              |                                                                                                                                                                                                                                           |
| `ended_at`                       | string                                                                                 | false    |              |                                                                                                                                                                                                                                           |
| `error_message`                  | string                                                                                 | false    |              | Error message is the raw terminal upstream error message from the root interception. Nil when the interception succeeded.                                                                                                                 |
| `error_type`                     | string                                                                                 | false    |              | Error type is the categorized terminal upstream error from the root interception, or nil when the interception succeeded. See the aibridge_interception_error_type enum for possible values.                                              |
| `id`                             | string                                                                                 | false    |              |                                                                                                                                                                                                                                           |
| `model`                          | string                                                                                 | false    |              |                                                                                                                                                                                                                                           |
| `prompt`                         | string                                                                                 | false    |              |                                                                                                                                                                                                                                           |
| `provider`                       | string                                                                                 | false    |              |                                                                                                                                                                                                                                           |
| `started_at`                     | string                                                                                 | false    |              |                                                                                                                                                                                                                                           |
| `token_usage`                    | [codersdk.AIBridgeSessionThreadsTokenUsage](#codersdkaibridgesessionthreadstokenusage) | false    |              |                                                                                                                                                                                                                                           |

## codersdk.AIBridgeToolCall

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "injected": true,
  "input": "string",
  "interception_id": "34d9b688-63ad-46f4-88b5-665c1e7f7824",
  "metadata": {
    "property1": null,
    "property2": null
  },
  "provider_response_id": "string",
  "server_url": "string",
  "tool": "string"
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description |
|------------------------|---------|----------|--------------|-------------|
| `created_at`           | string  | false    |              |             |
| `id`                   | string  | false    |              |             |
| `injected`             | boolean | false    |              |             |
| `input`                | string  | false    |              |             |
| `interception_id`      | string  | false    |              |             |
| `metadata`             | object  | false    |              |             |
| » `[any property]`     | any     | false    |              |             |
| `provider_response_id` | string  | false    |              |             |
| `server_url`           | string  | false    |              |             |
| `tool`                 | string  | false    |              |             |

## codersdk.AIBudgetLimit

```json
{
  "limit_source": "user_override",
  "spend_limit_micros": 0
}
```

### Properties

| Name                 | Type                                                         | Required | Restrictions | Description |
|----------------------|--------------------------------------------------------------|----------|--------------|-------------|
| `limit_source`       | [codersdk.AIBudgetLimitSource](#codersdkaibudgetlimitsource) | false    |              |             |
| `spend_limit_micros` | integer                                                      | false    |              |             |

## codersdk.AIBudgetLimitSource

```json
"user_override"
```

### Properties

#### Enumerated Values

| Value(s)                 |
|--------------------------|
| `group`, `user_override` |

## codersdk.AIConfig

```json
{
  "aibridge_proxy": {
    "allowed_private_cidrs": [
      "string"
    ],
    "api_dump_dir": "string",
    "cert_file": "string",
    "domain_allowlist": [
      "string"
    ],
    "enabled": true,
    "key_file": "string",
    "listen_addr": "string",
    "target": "string",
    "tls_cert_file": "string",
    "tls_key_file": "string",
    "upstream_proxy": "string",
    "upstream_proxy_ca": "string"
  },
  "bridge": {
    "actor_header_email": "string",
    "actor_header_id": "string",
    "actor_header_username": "string",
    "allow_byok": true,
    "api_dump_dir": "string",
    "budget_period": "string",
    "budget_policy": "string",
    "circuit_breaker_enabled": true,
    "circuit_breaker_failure_threshold": 0,
    "circuit_breaker_interval": 0,
    "circuit_breaker_max_requests": 0,
    "circuit_breaker_timeout": 0,
    "disable_content_recording": true,
    "enabled": true,
    "inject_coder_mcp_tools": true,
    "max_concurrency": 0,
    "rate_limit": 0,
    "retention": 0,
    "send_actor_headers": true,
    "structured_logging": true,
    "structured_logging_source": "string"
  },
  "chat": {
    "acquire_batch_size": 0,
    "debug_logging_enabled": true,
    "hook_allow_insecure": true,
    "hook_enabled": true,
    "hook_secret": "string",
    "hook_timeout": 0,
    "hook_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "max_attachments_per_chat": 0,
    "max_concurrent_recording_uploads": 0,
    "max_generation_retries": 0,
    "max_prompt_bytes": 0,
    "max_queued_messages_per_chat": 0,
    "max_steps_per_turn": 0,
    "stream_silence_timeout": 0
  }
}
```

### Properties

| Name             | Type                                                         | Required | Restrictions | Description |
|------------------|--------------------------------------------------------------|----------|--------------|-------------|
| `aibridge_proxy` | [codersdk.AIBridgeProxyConfig](#codersdkaibridgeproxyconfig) | false    |              |             |
| `bridge`         | [codersdk.AIBridgeConfig](#codersdkaibridgeconfig)           | false    |              |             |
| `chat`           | [codersdk.ChatConfig](#codersdkchatconfig)                   | false    |              |             |

## codersdk.AIGatewayKey

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "key_prefix": "string",
  "last_heartbeat_at": "2019-08-24T14:15:22Z",
  "name": "string"
}
```

### Properties

| Name                | Type   | Required | Restrictions | Description |
|---------------------|--------|----------|--------------|-------------|
| `created_at`        | string | false    |              |             |
| `id`                | string | false    |              |             |
| `key_prefix`        | string | false    |              |             |
| `last_heartbeat_at` | string | false    |              |             |
| `name`              | string | false    |              |             |

## codersdk.AIModelPrice

```json
{
  "cache_read_price": 0,
  "cache_write_price": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "input_price": 0,
  "model": "string",
  "output_price": 0,
  "provider": "string",
  "source": "default",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name                | Type                                                       | Required | Restrictions | Description |
|---------------------|------------------------------------------------------------|----------|--------------|-------------|
| `cache_read_price`  | integer                                                    | false    |              |             |
| `cache_write_price` | integer                                                    | false    |              |             |
| `created_at`        | string                                                     | false    |              |             |
| `input_price`       | integer                                                    | false    |              |             |
| `model`             | string                                                     | false    |              |             |
| `output_price`      | integer                                                    | false    |              |             |
| `provider`          | string                                                     | false    |              |             |
| `source`            | [codersdk.AIModelPriceSource](#codersdkaimodelpricesource) | false    |              |             |
| `updated_at`        | string                                                     | false    |              |             |

## codersdk.AIModelPriceSource

```json
"default"
```

### Properties

#### Enumerated Values

| Value(s)            |
|---------------------|
| `custom`, `default` |

## codersdk.AIModelPriceUpsert

```json
{
  "cache_read_price": 0,
  "cache_write_price": 0,
  "input_price": 0,
  "model": "string",
  "output_price": 0,
  "provider": "string"
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `cache_read_price`  | integer | false    |              |             |
| `cache_write_price` | integer | false    |              |             |
| `input_price`       | integer | false    |              |             |
| `model`             | string  | false    |              |             |
| `output_price`      | integer | false    |              |             |
| `provider`          | string  | false    |              |             |

## codersdk.AIProvider

```json
{
  "api_keys": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "masked": "string"
    }
  ],
  "base_url": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "settings": {},
  "status": {
    "warnings": [
      "string"
    ]
  },
  "type": "openai",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name           | Type                                                       | Required | Restrictions | Description                                            |
|----------------|------------------------------------------------------------|----------|--------------|--------------------------------------------------------|
| `api_keys`     | array of [codersdk.AIProviderKey](#codersdkaiproviderkey)  | false    |              |                                                        |
| `base_url`     | string                                                     | false    |              |                                                        |
| `created_at`   | string                                                     | false    |              |                                                        |
| `display_name` | string                                                     | false    |              |                                                        |
| `enabled`      | boolean                                                    | false    |              |                                                        |
| `icon`         | string                                                     | false    |              |                                                        |
| `id`           | string                                                     | false    |              |                                                        |
| `name`         | string                                                     | false    |              |                                                        |
| `settings`     | [codersdk.AIProviderSettings](#codersdkaiprovidersettings) | false    |              |                                                        |
| `status`       | [codersdk.AIProviderStatus](#codersdkaiproviderstatus)     | false    |              | Status carries runtime routing status; nil when empty. |
| `type`         | [codersdk.AIProviderType](#codersdkaiprovidertype)         | false    |              |                                                        |
| `updated_at`   | string                                                     | false    |              |                                                        |

## codersdk.AIProviderKey

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "masked": "string"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description |
|--------------|--------|----------|--------------|-------------|
| `created_at` | string | false    |              |             |
| `id`         | string | false    |              |             |
| `masked`     | string | false    |              |             |

## codersdk.AIProviderKeyMutation

```json
{
  "api_key": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description |
|-----------|--------|----------|--------------|-------------|
| `api_key` | string | false    |              |             |
| `id`      | string | false    |              |             |

## codersdk.AIProviderSettings

```json
{}
```

### Properties

None

## codersdk.AIProviderStatus

```json
{
  "warnings": [
    "string"
  ]
}
```

### Properties

| Name       | Type            | Required | Restrictions | Description |
|------------|-----------------|----------|--------------|-------------|
| `warnings` | array of string | false    |              |             |

## codersdk.AIProviderSummary

```json
{
  "deleted": true,
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "type": "openai"
}
```

### Properties

| Name           | Type                                               | Required | Restrictions | Description |
|----------------|----------------------------------------------------|----------|--------------|-------------|
| `deleted`      | boolean                                            | false    |              |             |
| `display_name` | string                                             | false    |              |             |
| `enabled`      | boolean                                            | false    |              |             |
| `icon`         | string                                             | false    |              |             |
| `id`           | string                                             | false    |              |             |
| `name`         | string                                             | false    |              |             |
| `type`         | [codersdk.AIProviderType](#codersdkaiprovidertype) | false    |              |             |

## codersdk.AIProviderType

```json
"openai"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                |
|---------------------------------------------------------------------------------------------------------|
| `anthropic`, `azure`, `bedrock`, `copilot`, `google`, `openai`, `openai-compat`, `openrouter`, `vercel` |

## codersdk.APIAllowListTarget

```json
{
  "id": "string",
  "type": "*"
}
```

### Properties

| Name   | Type                                           | Required | Restrictions | Description |
|--------|------------------------------------------------|----------|--------------|-------------|
| `id`   | string                                         | false    |              |             |
| `type` | [codersdk.RBACResource](#codersdkrbacresource) | false    |              |             |

## codersdk.APIKey

```json
{
  "allow_list": [
    {
      "id": "string",
      "type": "*"
    }
  ],
  "created_at": "2019-08-24T14:15:22Z",
  "expires_at": "2019-08-24T14:15:22Z",
  "id": "string",
  "last_used": "2019-08-24T14:15:22Z",
  "lifetime_seconds": 0,
  "login_type": "password",
  "scope": "all",
  "scopes": [
    "all"
  ],
  "token_name": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name               | Type                                                                | Required | Restrictions | Description                     |
|--------------------|---------------------------------------------------------------------|----------|--------------|---------------------------------|
| `allow_list`       | array of [codersdk.APIAllowListTarget](#codersdkapiallowlisttarget) | false    |              |                                 |
| `created_at`       | string                                                              | true     |              |                                 |
| `expires_at`       | string                                                              | true     |              |                                 |
| `id`               | string                                                              | true     |              |                                 |
| `last_used`        | string                                                              | true     |              |                                 |
| `lifetime_seconds` | integer                                                             | true     |              |                                 |
| `login_type`       | [codersdk.LoginType](#codersdklogintype)                            | true     |              |                                 |
| `scope`            | [codersdk.APIKeyScope](#codersdkapikeyscope)                        | false    |              | Deprecated: use Scopes instead. |
| `scopes`           | array of [codersdk.APIKeyScope](#codersdkapikeyscope)               | false    |              |                                 |
| `token_name`       | string                                                              | true     |              |                                 |
| `updated_at`       | string                                                              | true     |              |                                 |
| `user_id`          | string                                                              | true     |              |                                 |

#### Enumerated Values

| Property     | Value(s)                              |
|--------------|---------------------------------------|
| `login_type` | `github`, `oidc`, `password`, `token` |
| `scope`      | `all`, `application_connect`          |

## codersdk.APIKeyScope

```json
"all"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ai_gateway_key:*`, `ai_gateway_key:create`, `ai_gateway_key:delete`, `ai_gateway_key:read`, `ai_gateway_key:update`, `ai_model_price:*`, `ai_model_price:read`, `ai_model_price:update`, `ai_provider:*`, `ai_provider:create`, `ai_provider:delete`, `ai_provider:read`, `ai_provider:update`, `ai_seat:*`, `ai_seat:create`, `ai_seat:read`, `aibridge_interception:*`, `aibridge_interception:create`, `aibridge_interception:read`, `aibridge_interception:update`, `all`, `api_key:*`, `api_key:create`, `api_key:delete`, `api_key:read`, `api_key:update`, `application_connect`, `assign_org_role:*`, `assign_org_role:assign`, `assign_org_role:create`, `assign_org_role:delete`, `assign_org_role:read`, `assign_org_role:unassign`, `assign_org_role:update`, `assign_role:*`, `assign_role:assign`, `assign_role:read`, `assign_role:unassign`, `audit_log:*`, `audit_log:create`, `audit_log:read`, `boundary_log:*`, `boundary_log:create`, `boundary_log:delete`, `boundary_log:read`, `boundary_usage:*`, `boundary_usage:delete`, `boundary_usage:read`, `boundary_usage:update`, `chat:*`, `chat:create`, `chat:delete`, `chat:read`, `chat:share`, `chat:update`, `chat_model_config:*`, `chat_model_config:create`, `chat_model_config:delete`, `chat_model_config:read`, `chat_model_config:share`, `chat_model_config:update`, `coder:all`, `coder:apikeys.manage_self`, `coder:application_connect`, `coder:templates.author`, `coder:templates.build`, `coder:workspaces.access`, `coder:workspaces.create`, `coder:workspaces.delete`, `coder:workspaces.operate`, `connection_log:*`, `connection_log:read`, `connection_log:update`, `crypto_key:*`, `crypto_key:create`, `crypto_key:delete`, `crypto_key:read`, `crypto_key:update`, `debug_info:*`, `debug_info:read`, `deployment_config:*`, `deployment_config:read`, `deployment_config:update`, `deployment_stats:*`, `deployment_stats:read`, `file:*`, `file:create`, `file:read`, `group:*`, `group:create`, `group:delete`, `group:read`, `group:update`, `group_member:*`, `group_member:read`, `idpsync_settings:*`, `idpsync_settings:read`, `idpsync_settings:update`, `inbox_notification:*`, `inbox_notification:create`, `inbox_notification:read`, `inbox_notification:update`, `license:*`, `license:create`, `license:delete`, `license:read`, `mcp_server_config:*`, `mcp_server_config:create`, `mcp_server_config:delete`, `mcp_server_config:read`, `mcp_server_config:share`, `mcp_server_config:update`, `notification_message:*`, `notification_message:create`, `notification_message:delete`, `notification_message:read`, `notification_message:update`, `notification_preference:*`, `notification_preference:read`, `notification_preference:update`, `notification_template:*`, `notification_template:read`, `notification_template:update`, `oauth2_app:*`, `oauth2_app:create`, `oauth2_app:delete`, `oauth2_app:read`, `oauth2_app:update`, `oauth2_app_code_token:*`, `oauth2_app_code_token:create`, `oauth2_app_code_token:delete`, `oauth2_app_code_token:read`, `oauth2_app_secret:*`, `oauth2_app_secret:create`, `oauth2_app_secret:delete`, `oauth2_app_secret:read`, `oauth2_app_secret:update`, `organization:*`, `organization:create`, `organization:delete`, `organization:read`, `organization:update`, `organization_member:*`, `organization_member:create`, `organization_member:delete`, `organization_member:read`, `organization_member:update`, `prebuilt_workspace:*`, `prebuilt_workspace:delete`, `prebuilt_workspace:update`, `provisioner_daemon:*`, `provisioner_daemon:create`, `provisioner_daemon:delete`, `provisioner_daemon:read`, `provisioner_daemon:update`, `provisioner_jobs:*`, `provisioner_jobs:create`, `provisioner_jobs:read`, `provisioner_jobs:update`, `replicas:*`, `replicas:read`, `system:*`, `system:create`, `system:delete`, `system:read`, `system:update`, `tailnet_coordinator:*`, `tailnet_coordinator:create`, `tailnet_coordinator:delete`, `tailnet_coordinator:read`, `tailnet_coordinator:update`, `template:*`, `template:create`, `template:delete`, `template:read`, `template:update`, `template:use`, `template:view_insights`, `usage_event:*`, `usage_event:create`, `usage_event:read`, `usage_event:update`, `user:*`, `user:create`, `user:delete`, `user:read`, `user:read_personal`, `user:update`, `user:update_personal`, `user_secret:*`, `user_secret:create`, `user_secret:delete`, `user_secret:read`, `user_secret:update`, `user_skill:*`, `user_skill:create`, `user_skill:delete`, `user_skill:read`, `user_skill:update`, `webpush_subscription:*`, `webpush_subscription:create`, `webpush_subscription:delete`, `webpush_subscription:read`, `workspace:*`, `workspace:application_connect`, `workspace:create`, `workspace:create_agent`, `workspace:delete`, `workspace:delete_agent`, `workspace:read`, `workspace:share`, `workspace:ssh`, `workspace:start`, `workspace:stop`, `workspace:update`, `workspace:update_agent`, `workspace_agent_devcontainers:*`, `workspace_agent_devcontainers:create`, `workspace_agent_resource_monitor:*`, `workspace_agent_resource_monitor:create`, `workspace_agent_resource_monitor:read`, `workspace_agent_resource_monitor:update`, `workspace_build_orchestration:*`, `workspace_build_orchestration:create`, `workspace_build_orchestration:delete`, `workspace_build_orchestration:read`, `workspace_build_orchestration:update`, `workspace_dormant:*`, `workspace_dormant:application_connect`, `workspace_dormant:create`, `workspace_dormant:create_agent`, `workspace_dormant:delete`, `workspace_dormant:delete_agent`, `workspace_dormant:read`, `workspace_dormant:share`, `workspace_dormant:ssh`, `workspace_dormant:start`, `workspace_dormant:stop`, `workspace_dormant:update`, `workspace_dormant:update_agent`, `workspace_proxy:*`, `workspace_proxy:create`, `workspace_proxy:delete`, `workspace_proxy:read`, `workspace_proxy:update` |

## codersdk.AddLicenseRequest

```json
{
  "license": "string"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description |
|-----------|--------|----------|--------------|-------------|
| `license` | string | true     |              |             |

## codersdk.AgentChatSendShortcut

```json
"enter"
```

### Properties

#### Enumerated Values

| Value(s)                  |
|---------------------------|
| `enter`, `modifier_enter` |

## codersdk.AgentConnectionTiming

```json
{
  "ended_at": "2019-08-24T14:15:22Z",
  "stage": "init",
  "started_at": "2019-08-24T14:15:22Z",
  "workspace_agent_id": "string",
  "workspace_agent_name": "string"
}
```

### Properties

| Name                   | Type                                         | Required | Restrictions | Description |
|------------------------|----------------------------------------------|----------|--------------|-------------|
| `ended_at`             | string                                       | false    |              |             |
| `stage`                | [codersdk.TimingStage](#codersdktimingstage) | false    |              |             |
| `started_at`           | string                                       | false    |              |             |
| `workspace_agent_id`   | string                                       | false    |              |             |
| `workspace_agent_name` | string                                       | false    |              |             |

## codersdk.AgentDisplayMode

```json
"auto"
```

### Properties

#### Enumerated Values

| Value(s)                                      |
|-----------------------------------------------|
| `always_collapsed`, `always_expanded`, `auto` |

## codersdk.AgentFirewallLog

```json
{
  "allowed": true,
  "captured_at": "2019-08-24T14:15:22Z",
  "created_at": "2019-08-24T14:15:22Z",
  "detail": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "matched_rule": "string",
  "method": "string",
  "proto": "string",
  "sequence_number": 0,
  "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82"
}
```

### Properties

| Name              | Type    | Required | Restrictions | Description |
|-------------------|---------|----------|--------------|-------------|
| `allowed`         | boolean | false    |              |             |
| `captured_at`     | string  | false    |              |             |
| `created_at`      | string  | false    |              |             |
| `detail`          | string  | false    |              |             |
| `id`              | string  | false    |              |             |
| `matched_rule`    | string  | false    |              |             |
| `method`          | string  | false    |              |             |
| `proto`           | string  | false    |              |             |
| `sequence_number` | integer | false    |              |             |
| `session_id`      | string  | false    |              |             |

## codersdk.AgentFirewallSession

```json
{
  "confined_process": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "started_at": "2019-08-24T14:15:22Z",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Properties

| Name               | Type   | Required | Restrictions | Description |
|--------------------|--------|----------|--------------|-------------|
| `confined_process` | string | false    |              |             |
| `id`               | string | false    |              |             |
| `owner_id`         | string | false    |              |             |
| `started_at`       | string | false    |              |             |
| `workspace_id`     | string | false    |              |             |

## codersdk.AgentFirewallSessionLogsResponse

```json
{
  "results": [
    {
      "allowed": true,
      "captured_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "detail": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "matched_rule": "string",
      "method": "string",
      "proto": "string",
      "sequence_number": 0,
      "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82"
    }
  ]
}
```

### Properties

| Name      | Type                                                            | Required | Restrictions | Description |
|-----------|-----------------------------------------------------------------|----------|--------------|-------------|
| `results` | array of [codersdk.AgentFirewallLog](#codersdkagentfirewalllog) | false    |              |             |

## codersdk.AgentScriptTiming

```json
{
  "display_name": "string",
  "ended_at": "2019-08-24T14:15:22Z",
  "exit_code": 0,
  "stage": "init",
  "started_at": "2019-08-24T14:15:22Z",
  "status": "string",
  "workspace_agent_id": "string",
  "workspace_agent_name": "string"
}
```

### Properties

| Name                   | Type                                         | Required | Restrictions | Description |
|------------------------|----------------------------------------------|----------|--------------|-------------|
| `display_name`         | string                                       | false    |              |             |
| `ended_at`             | string                                       | false    |              |             |
| `exit_code`            | integer                                      | false    |              |             |
| `stage`                | [codersdk.TimingStage](#codersdktimingstage) | false    |              |             |
| `started_at`           | string                                       | false    |              |             |
| `status`               | string                                       | false    |              |             |
| `workspace_agent_id`   | string                                       | false    |              |             |
| `workspace_agent_name` | string                                       | false    |              |             |

## codersdk.AgentSubsystem

```json
"envbox"
```

### Properties

#### Enumerated Values

| Value(s)                            |
|-------------------------------------|
| `envbox`, `envbuilder`, `exectrace` |

## codersdk.AppFamilyName

```json
"vscode"
```

### Properties

#### Enumerated Values

| Value(s)                                                            |
|---------------------------------------------------------------------|
| `jetbrains`, `reconnecting_pty`, `sftp`, `ssh`, `unknown`, `vscode` |

## codersdk.AppHostResponse

```json
{
  "host": "string"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description                                                   |
|--------|--------|----------|--------------|---------------------------------------------------------------|
| `host` | string | false    |              | Host is the externally accessible URL for the Coder instance. |

## codersdk.AppearanceConfig

```json
{
  "announcement_banners": [
    {
      "background_color": "string",
      "enabled": true,
      "message": "string"
    }
  ],
  "application_name": "string",
  "codernauts_enabled": true,
  "docs_url": "string",
  "logo_url": "string",
  "service_banner": {
    "background_color": "string",
    "enabled": true,
    "message": "string"
  },
  "support_links": [
    {
      "icon": "bug",
      "location": "navbar",
      "name": "string",
      "target": "string"
    }
  ]
}
```

### Properties

| Name                   | Type                                                    | Required | Restrictions | Description                                                         |
|------------------------|---------------------------------------------------------|----------|--------------|---------------------------------------------------------------------|
| `announcement_banners` | array of [codersdk.BannerConfig](#codersdkbannerconfig) | false    |              |                                                                     |
| `application_name`     | string                                                  | false    |              |                                                                     |
| `codernauts_enabled`   | boolean                                                 | false    |              |                                                                     |
| `docs_url`             | string                                                  | false    |              |                                                                     |
| `logo_url`             | string                                                  | false    |              |                                                                     |
| `service_banner`       | [codersdk.BannerConfig](#codersdkbannerconfig)          | false    |              | Deprecated: ServiceBanner has been replaced by AnnouncementBanners. |
| `support_links`        | array of [codersdk.LinkConfig](#codersdklinkconfig)     | false    |              |                                                                     |

## codersdk.ArchiveTemplateVersionsRequest

```json
{
  "all": true
}
```

### Properties

| Name  | Type    | Required | Restrictions | Description                                                                                                              |
|-------|---------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------|
| `all` | boolean | false    |              | By default, only failed versions are archived. Set this to true to archive all unused versions regardless of job status. |

## codersdk.AssignableRoles

```json
{
  "assignable": true,
  "built_in": true,
  "display_name": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_member_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "organization_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "site_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "user_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ]
}
```

### Properties

| Name                              | Type                                                | Required | Restrictions | Description                                                                                            |
|-----------------------------------|-----------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------|
| `assignable`                      | boolean                                             | false    |              |                                                                                                        |
| `built_in`                        | boolean                                             | false    |              | Built in roles are immutable                                                                           |
| `display_name`                    | string                                              | false    |              |                                                                                                        |
| `name`                            | string                                              | false    |              |                                                                                                        |
| `organization_id`                 | string                                              | false    |              |                                                                                                        |
| `organization_member_permissions` | array of [codersdk.Permission](#codersdkpermission) | false    |              | Organization member permissions are specific for the organization in the field 'OrganizationID' above. |
| `organization_permissions`        | array of [codersdk.Permission](#codersdkpermission) | false    |              | Organization permissions are specific for the organization in the field 'OrganizationID' above.        |
| `site_permissions`                | array of [codersdk.Permission](#codersdkpermission) | false    |              |                                                                                                        |
| `user_permissions`                | array of [codersdk.Permission](#codersdkpermission) | false    |              |                                                                                                        |

## codersdk.AuditAction

```json
"create"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                        |
|-------------------------------------------------------------------------------------------------------------------------------------------------|
| `close`, `connect`, `create`, `delete`, `disconnect`, `login`, `logout`, `open`, `register`, `request_password_reset`, `start`, `stop`, `write` |

## codersdk.AuditDiff

```json
{
  "property1": {
    "new": null,
    "old": null,
    "secret": true
  },
  "property2": {
    "new": null,
    "old": null,
    "secret": true
  }
}
```

### Properties

| Name             | Type                                               | Required | Restrictions | Description |
|------------------|----------------------------------------------------|----------|--------------|-------------|
| `[any property]` | [codersdk.AuditDiffField](#codersdkauditdifffield) | false    |              |             |

## codersdk.AuditDiffField

```json
{
  "new": null,
  "old": null,
  "secret": true
}
```

### Properties

| Name     | Type    | Required | Restrictions | Description |
|----------|---------|----------|--------------|-------------|
| `new`    | any     | false    |              |             |
| `old`    | any     | false    |              |             |
| `secret` | boolean | false    |              |             |

## codersdk.AuditLog

```json
{
  "action": "create",
  "additional_fields": {},
  "description": "string",
  "diff": {
    "property1": {
      "new": null,
      "old": null,
      "secret": true
    },
    "property2": {
      "new": null,
      "old": null,
      "secret": true
    }
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "ip": "string",
  "is_deleted": true,
  "organization": {
    "display_name": "string",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string"
  },
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "request_id": "266ea41d-adf5-480b-af50-15b940c2b846",
  "resource_icon": "string",
  "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
  "resource_link": "string",
  "resource_target": "string",
  "resource_type": "template",
  "status_code": 0,
  "time": "2019-08-24T14:15:22Z",
  "user": {
    "avatar_url": "http://example.com",
    "created_at": "2019-08-24T14:15:22Z",
    "email": "user@example.com",
    "has_ai_seat": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "is_service_account": true,
    "last_seen_at": "2019-08-24T14:15:22Z",
    "login_type": "",
    "name": "string",
    "organization_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "roles": [
      {
        "display_name": "string",
        "name": "string",
        "organization_id": "string"
      }
    ],
    "status": "active",
    "theme_preference": "string",
    "updated_at": "2019-08-24T14:15:22Z",
    "username": "string"
  },
  "user_agent": "string"
}
```

### Properties

| Name                | Type                                                         | Required | Restrictions | Description                                  |
|---------------------|--------------------------------------------------------------|----------|--------------|----------------------------------------------|
| `action`            | [codersdk.AuditAction](#codersdkauditaction)                 | false    |              |                                              |
| `additional_fields` | object                                                       | false    |              |                                              |
| `description`       | string                                                       | false    |              |                                              |
| `diff`              | [codersdk.AuditDiff](#codersdkauditdiff)                     | false    |              |                                              |
| `id`                | string                                                       | false    |              |                                              |
| `ip`                | string                                                       | false    |              |                                              |
| `is_deleted`        | boolean                                                      | false    |              |                                              |
| `organization`      | [codersdk.MinimalOrganization](#codersdkminimalorganization) | false    |              |                                              |
| `organization_id`   | string                                                       | false    |              | Deprecated: Use 'organization.id' instead.   |
| `request_id`        | string                                                       | false    |              |                                              |
| `resource_icon`     | string                                                       | false    |              |                                              |
| `resource_id`       | string                                                       | false    |              |                                              |
| `resource_link`     | string                                                       | false    |              |                                              |
| `resource_target`   | string                                                       | false    |              | Resource target is the name of the resource. |
| `resource_type`     | [codersdk.ResourceType](#codersdkresourcetype)               | false    |              |                                              |
| `status_code`       | integer                                                      | false    |              |                                              |
| `time`              | string                                                       | false    |              |                                              |
| `user`              | [codersdk.User](#codersdkuser)                               | false    |              |                                              |
| `user_agent`        | string                                                       | false    |              |                                              |

## codersdk.AuditLogResponse

```json
{
  "audit_logs": [
    {
      "action": "create",
      "additional_fields": {},
      "description": "string",
      "diff": {
        "property1": {
          "new": null,
          "old": null,
          "secret": true
        },
        "property2": {
          "new": null,
          "old": null,
          "secret": true
        }
      },
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "ip": "string",
      "is_deleted": true,
      "organization": {
        "display_name": "string",
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "request_id": "266ea41d-adf5-480b-af50-15b940c2b846",
      "resource_icon": "string",
      "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
      "resource_link": "string",
      "resource_target": "string",
      "resource_type": "template",
      "status_code": 0,
      "time": "2019-08-24T14:15:22Z",
      "user": {
        "avatar_url": "http://example.com",
        "created_at": "2019-08-24T14:15:22Z",
        "email": "user@example.com",
        "has_ai_seat": true,
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "is_service_account": true,
        "last_seen_at": "2019-08-24T14:15:22Z",
        "login_type": "",
        "name": "string",
        "organization_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "roles": [
          {
            "display_name": "string",
            "name": "string",
            "organization_id": "string"
          }
        ],
        "status": "active",
        "theme_preference": "string",
        "updated_at": "2019-08-24T14:15:22Z",
        "username": "string"
      },
      "user_agent": "string"
    }
  ],
  "count": 0,
  "count_cap": 0
}
```

### Properties

| Name         | Type                                            | Required | Restrictions | Description |
|--------------|-------------------------------------------------|----------|--------------|-------------|
| `audit_logs` | array of [codersdk.AuditLog](#codersdkauditlog) | false    |              |             |
| `count`      | integer                                         | false    |              |             |
| `count_cap`  | integer                                         | false    |              |             |

## codersdk.AuthMethod

```json
{
  "enabled": true
}
```

### Properties

| Name      | Type    | Required | Restrictions | Description |
|-----------|---------|----------|--------------|-------------|
| `enabled` | boolean | false    |              |             |

## codersdk.AuthMethods

```json
{
  "github": {
    "default_provider_configured": true,
    "enabled": true
  },
  "oidc": {
    "enabled": true,
    "iconUrl": "string",
    "signInText": "string"
  },
  "password": {
    "enabled": true
  },
  "terms_of_service_url": "string"
}
```

### Properties

| Name                   | Type                                                   | Required | Restrictions | Description |
|------------------------|--------------------------------------------------------|----------|--------------|-------------|
| `github`               | [codersdk.GithubAuthMethod](#codersdkgithubauthmethod) | false    |              |             |
| `oidc`                 | [codersdk.OIDCAuthMethod](#codersdkoidcauthmethod)     | false    |              |             |
| `password`             | [codersdk.AuthMethod](#codersdkauthmethod)             | false    |              |             |
| `terms_of_service_url` | string                                                 | false    |              |             |

## codersdk.AuthorizationCheck

```json
{
  "action": "create",
  "object": {
    "any_org": true,
    "organization_id": "string",
    "owner_id": "string",
    "resource_id": "string",
    "resource_type": "*"
  }
}
```

AuthorizationCheck is used to check if the currently authenticated user (or the specified user) can do a given action to a given set of objects.

### Properties

| Name     | Type                                                         | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
|----------|--------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action` | [codersdk.RBACAction](#codersdkrbacaction)                   | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `object` | [codersdk.AuthorizationObject](#codersdkauthorizationobject) | false    |              | Object can represent a "set" of objects, such as: all workspaces in an organization, all workspaces owned by me, and all workspaces across the entire product. When defining an object, use the most specific language when possible to produce the smallest set. Meaning to set as many fields on 'Object' as you can. Example, if you want to check if you can update all workspaces owned by 'me', try to also add an 'OrganizationID' to the settings. Omitting the 'OrganizationID' could produce the incorrect value, as workspaces have both `user` and `organization` owners. |

#### Enumerated Values

| Property | Value(s)                             |
|----------|--------------------------------------|
| `action` | `create`, `delete`, `read`, `update` |

## codersdk.AuthorizationObject

```json
{
  "any_org": true,
  "organization_id": "string",
  "owner_id": "string",
  "resource_id": "string",
  "resource_type": "*"
}
```

AuthorizationObject can represent a "set" of objects, such as: all workspaces in an organization, all workspaces owned by me, all workspaces across the entire product.

### Properties

| Name              | Type                                           | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                          |
|-------------------|------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `any_org`         | boolean                                        | false    |              | Any org (optional) will disregard the org_owner when checking for permissions. This cannot be set to true if the OrganizationID is set.                                                                                                                                                                                                                              |
| `organization_id` | string                                         | false    |              | Organization ID (optional) adds the set constraint to all resources owned by a given organization.                                                                                                                                                                                                                                                                   |
| `owner_id`        | string                                         | false    |              | Owner ID (optional) adds the set constraint to all resources owned by a given user.                                                                                                                                                                                                                                                                                  |
| `resource_id`     | string                                         | false    |              | Resource ID (optional) reduces the set to a singular resource. This assigns a resource ID to the resource type, eg: a single workspace. The rbac library will not fetch the resource from the database, so if you are using this option, you should also set the owner ID and organization ID if possible. Be as specific as possible using all the fields relevant. |
| `resource_type`   | [codersdk.RBACResource](#codersdkrbacresource) | false    |              | Resource type is the name of the resource. `./coderd/rbac/object.go` has the list of valid resource types.                                                                                                                                                                                                                                                           |

## codersdk.AuthorizationRequest

```json
{
  "checks": {
    "property1": {
      "action": "create",
      "object": {
        "any_org": true,
        "organization_id": "string",
        "owner_id": "string",
        "resource_id": "string",
        "resource_type": "*"
      }
    },
    "property2": {
      "action": "create",
      "object": {
        "any_org": true,
        "organization_id": "string",
        "owner_id": "string",
        "resource_id": "string",
        "resource_type": "*"
      }
    }
  }
}
```

### Properties

| Name               | Type                                                       | Required | Restrictions | Description                                                                                                                                                                                                                                                                      |
|--------------------|------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `checks`           | object                                                     | false    |              | Checks is a map keyed with an arbitrary string to a permission check. The key can be any string that is helpful to the caller, and allows multiple permission checks to be run in a single request. The key ensures that each permission check has the same key in the response. |
| » `[any property]` | [codersdk.AuthorizationCheck](#codersdkauthorizationcheck) | false    |              | It is used to check if the currently authenticated user (or the specified user) can do a given action to a given set of objects.                                                                                                                                                 |

## codersdk.AuthorizationResponse

```json
{
  "property1": true,
  "property2": true
}
```

### Properties

| Name             | Type    | Required | Restrictions | Description |
|------------------|---------|----------|--------------|-------------|
| `[any property]` | boolean | false    |              |             |

## codersdk.AutomaticUpdates

```json
"always"
```

### Properties

#### Enumerated Values

| Value(s)          |
|-------------------|
| `always`, `never` |

## codersdk.BannerConfig

```json
{
  "background_color": "string",
  "enabled": true,
  "message": "string"
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description |
|--------------------|---------|----------|--------------|-------------|
| `background_color` | string  | false    |              |             |
| `enabled`          | boolean | false    |              |             |
| `message`          | string  | false    |              |             |

## codersdk.BuildInfoResponse

```json
{
  "agent_api_version": "string",
  "dashboard_url": "string",
  "deployment_id": "string",
  "external_url": "string",
  "oauth2_provider": true,
  "provisioner_api_version": "string",
  "telemetry": true,
  "upgrade_message": "string",
  "version": "string",
  "webpush_public_key": "string",
  "workspace_proxy": true
}
```

### Properties

| Name                      | Type    | Required | Restrictions | Description                                                                                                                                                         |
|---------------------------|---------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_api_version`       | string  | false    |              | Agent api version is the current version of the Agent API (back versions MAY still be supported).                                                                   |
| `dashboard_url`           | string  | false    |              | Dashboard URL is the URL to hit the deployment's dashboard. For external workspace proxies, this is the coderd they are connected to.                               |
| `deployment_id`           | string  | false    |              | Deployment ID is the unique identifier for this deployment.                                                                                                         |
| `external_url`            | string  | false    |              | External URL references the current Coder version. For production builds, this will link directly to a release. For development builds, this will link to a commit. |
| `oauth2_provider`         | boolean | false    |              | Oauth2 provider reports whether the OAuth 2.1 authorization server is enabled. The dashboard uses it to show or hide OAuth2 navigation.                             |
| `provisioner_api_version` | string  | false    |              | Provisioner api version is the current version of the Provisioner API                                                                                               |
| `telemetry`               | boolean | false    |              | Telemetry is a boolean that indicates whether telemetry is enabled.                                                                                                 |
| `upgrade_message`         | string  | false    |              | Upgrade message is the message displayed to users when an outdated client is detected.                                                                              |
| `version`                 | string  | false    |              | Version returns the semantic version of the build.                                                                                                                  |
| `webpush_public_key`      | string  | false    |              | Webpush public key is the public key for push notifications via Web Push.                                                                                           |
| `workspace_proxy`         | boolean | false    |              |                                                                                                                                                                     |

## codersdk.BuildReason

```json
"initiator"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                            |
|-------------------------------------------------------------------------------------------------------------------------------------|
| `autostart`, `autostop`, `cli`, `dashboard`, `dormancy`, `initiator`, `jetbrains_connection`, `ssh_connection`, `vscode_connection` |

## codersdk.CORSBehavior

```json
"simple"
```

### Properties

#### Enumerated Values

| Value(s)             |
|----------------------|
| `passthru`, `simple` |

## codersdk.ChangePasswordWithOneTimePasscodeRequest

```json
{
  "email": "user@example.com",
  "one_time_passcode": "string",
  "password": "string"
}
```

### Properties

| Name                | Type   | Required | Restrictions | Description |
|---------------------|--------|----------|--------------|-------------|
| `email`             | string | true     |              |             |
| `one_time_passcode` | string | true     |              |             |
| `password`          | string | true     |              |             |

## codersdk.Chat

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "archived": true,
  "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
  "children": [
    {
      "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
      "archived": true,
      "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
      "children": [],
      "client_type": "ui",
      "context": {
        "dirty": true,
        "dirty_since": "2019-08-24T14:15:22Z",
        "error": "string",
        "resources": [
          {
            "error": "string",
            "kind": "instruction_file",
            "size_bytes": 0,
            "skill_description": "string",
            "skill_name": "string",
            "source": "string",
            "status": "ok",
            "tools": [
              {
                "description": "string",
                "name": "string"
              }
            ]
          }
        ]
      },
      "created_at": "2019-08-24T14:15:22Z",
      "diff_status": {
        "additions": 0,
        "approved": true,
        "author_avatar_url": "string",
        "author_login": "string",
        "base_branch": "string",
        "changed_files": 0,
        "changes_requested": true,
        "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
        "commits": 0,
        "deletions": 0,
        "head_branch": "string",
        "pr_number": 0,
        "pull_request_draft": true,
        "pull_request_state": "string",
        "pull_request_title": "string",
        "refreshed_at": "2019-08-24T14:15:22Z",
        "reviewer_count": 0,
        "stale_at": "2019-08-24T14:15:22Z",
        "url": "string"
      },
      "files": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "mime_type": "string",
          "name": "string",
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
          "size_bytes": 0
        }
      ],
      "has_unread": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "inline_mcp_servers": [
        {
          "allow_in_subagents": true,
          "created_at": "2019-08-24T14:15:22Z",
          "forward_coder_headers": true,
          "has_custom_headers": true,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "slug": "string",
          "tool_allow_list": [
            "string"
          ],
          "tool_deny_list": [
            "string"
          ],
          "updated_at": "2019-08-24T14:15:22Z",
          "url": "string"
        }
      ],
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "last_error": {
        "detail": "string",
        "kind": "generic",
        "message": "string",
        "provider": "string",
        "retryable": true,
        "status_code": 0
      },
      "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
      "last_reasoning_effort": "string",
      "last_turn_summary": "string",
      "mcp_server_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "owner_name": "string",
      "owner_username": "string",
      "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
      "pin_order": 0,
      "plan_mode": "plan",
      "queued_for_capacity": true,
      "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
      "shared": true,
      "status": "waiting",
      "summary": "string",
      "title": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "warnings": [
        "string"
      ],
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ],
  "client_type": "ui",
  "context": {
    "dirty": true,
    "dirty_since": "2019-08-24T14:15:22Z",
    "error": "string",
    "resources": [
      {
        "error": "string",
        "kind": "instruction_file",
        "size_bytes": 0,
        "skill_description": "string",
        "skill_name": "string",
        "source": "string",
        "status": "ok",
        "tools": [
          {
            "description": "string",
            "name": "string"
          }
        ]
      }
    ]
  },
  "created_at": "2019-08-24T14:15:22Z",
  "diff_status": {
    "additions": 0,
    "approved": true,
    "author_avatar_url": "string",
    "author_login": "string",
    "base_branch": "string",
    "changed_files": 0,
    "changes_requested": true,
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "commits": 0,
    "deletions": 0,
    "head_branch": "string",
    "pr_number": 0,
    "pull_request_draft": true,
    "pull_request_state": "string",
    "pull_request_title": "string",
    "refreshed_at": "2019-08-24T14:15:22Z",
    "reviewer_count": 0,
    "stale_at": "2019-08-24T14:15:22Z",
    "url": "string"
  },
  "files": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "mime_type": "string",
      "name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "size_bytes": 0
    }
  ],
  "has_unread": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "created_at": "2019-08-24T14:15:22Z",
      "forward_coder_headers": true,
      "has_custom_headers": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "updated_at": "2019-08-24T14:15:22Z",
      "url": "string"
    }
  ],
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "last_error": {
    "detail": "string",
    "kind": "generic",
    "message": "string",
    "provider": "string",
    "retryable": true,
    "status_code": 0
  },
  "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
  "last_reasoning_effort": "string",
  "last_turn_summary": "string",
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "owner_username": "string",
  "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
  "pin_order": 0,
  "plan_mode": "plan",
  "queued_for_capacity": true,
  "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
  "shared": true,
  "status": "waiting",
  "summary": "string",
  "title": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "string"
  ],
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Properties

| Name                    | Type                                                            | Required | Restrictions | Description                                                                                                                                                                                                                                                                |
|-------------------------|-----------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_id`              | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `archived`              | boolean                                                         | false    |              |                                                                                                                                                                                                                                                                            |
| `build_id`              | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `children`              | array of [codersdk.Chat](#codersdkchat)                         | false    |              | Children holds child (subagent) chats nested under this root chat. Always initialized to an empty slice so the JSON field is present as []. Child chats cannot create their own subagents, so nesting depth is capped at 1 and this slice is always empty for child chats. |
| `client_type`           | [codersdk.ChatClientType](#codersdkchatclienttype)              | false    |              |                                                                                                                                                                                                                                                                            |
| `context`               | [codersdk.ChatContext](#codersdkchatcontext)                    | false    |              | Context reports the chat's pinned workspace-context state and whether it has drifted from the agent's latest pushed snapshot. Nil when the chat has no pinned context yet.                                                                                                 |
| `created_at`            | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `diff_status`           | [codersdk.ChatDiffStatus](#codersdkchatdiffstatus)              | false    |              |                                                                                                                                                                                                                                                                            |
| `files`                 | array of [codersdk.ChatFileMetadata](#codersdkchatfilemetadata) | false    |              |                                                                                                                                                                                                                                                                            |
| `has_unread`            | boolean                                                         | false    |              | Has unread is true when assistant messages exist beyond the owner's read cursor, which updates on stream connect and disconnect and via UpdateChatRequest.Read.                                                                                                            |
| `id`                    | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `inline_mcp_servers`    | array of [codersdk.InlineMCPServer](#codersdkinlinemcpserver)   | false    |              | Inline mcp servers lists the inline MCP servers declared on the chat, without headers. Only the single-chat GET sets it. Experimental.                                                                                                                                     |
| `labels`                | object                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| » `[any property]`      | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `last_error`            | [codersdk.ChatError](#codersdkchaterror)                        | false    |              |                                                                                                                                                                                                                                                                            |
| `last_model_config_id`  | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `last_reasoning_effort` | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `last_turn_summary`     | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `mcp_server_ids`        | array of string                                                 | false    |              |                                                                                                                                                                                                                                                                            |
| `organization_id`       | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `owner_id`              | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `owner_name`            | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `owner_username`        | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `parent_chat_id`        | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `pin_order`             | integer                                                         | false    |              |                                                                                                                                                                                                                                                                            |
| `plan_mode`             | [codersdk.ChatPlanMode](#codersdkchatplanmode)                  | false    |              |                                                                                                                                                                                                                                                                            |
| `queued_for_capacity`   | boolean                                                         | false    |              | Queued for capacity reports that the chat is waiting for a concurrent agent slot. Single-chat reads derive it; list responses leave it false.                                                                                                                              |
| `root_chat_id`          | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `shared`                | boolean                                                         | false    |              | Shared is true when this chat's root chat has explicit user or group ACL entries.                                                                                                                                                                                          |
| `status`                | [codersdk.ChatStatus](#codersdkchatstatus)                      | false    |              |                                                                                                                                                                                                                                                                            |
| `summary`               | string                                                          | false    |              | Summary is the persisted whole-chat summary, generated in the background. It is nil until the first summary has been produced.                                                                                                                                             |
| `title`                 | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `updated_at`            | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |
| `warnings`              | array of string                                                 | false    |              |                                                                                                                                                                                                                                                                            |
| `workspace_id`          | string                                                          | false    |              |                                                                                                                                                                                                                                                                            |

## codersdk.ChatACL

```json
{
  "groups": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "members": [
        {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        }
      ],
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "role": "read",
      "source": "user",
      "total_member_count": 0
    }
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "role": "read",
      "username": "string"
    }
  ]
}
```

### Properties

| Name     | Type                                              | Required | Restrictions | Description |
|----------|---------------------------------------------------|----------|--------------|-------------|
| `groups` | array of [codersdk.ChatGroup](#codersdkchatgroup) | false    |              |             |
| `users`  | array of [codersdk.ChatUser](#codersdkchatuser)   | false    |              |             |

## codersdk.ChatAutoArchiveDaysResponse

```json
{
  "auto_archive_days": 0
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `auto_archive_days` | integer | false    |              |             |

## codersdk.ChatBusyBehavior

```json
"queue"
```

### Properties

#### Enumerated Values

| Value(s)             |
|----------------------|
| `interrupt`, `queue` |

## codersdk.ChatClientType

```json
"ui"
```

### Properties

#### Enumerated Values

| Value(s)    |
|-------------|
| `api`, `ui` |

## codersdk.ChatConfig

```json
{
  "acquire_batch_size": 0,
  "debug_logging_enabled": true,
  "hook_allow_insecure": true,
  "hook_enabled": true,
  "hook_secret": "string",
  "hook_timeout": 0,
  "hook_url": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  },
  "max_attachments_per_chat": 0,
  "max_concurrent_recording_uploads": 0,
  "max_generation_retries": 0,
  "max_prompt_bytes": 0,
  "max_queued_messages_per_chat": 0,
  "max_steps_per_turn": 0,
  "stream_silence_timeout": 0
}
```

### Properties

| Name                               | Type                       | Required | Restrictions | Description                                                                                                                               |
|------------------------------------|----------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------|
| `acquire_batch_size`               | integer                    | false    |              |                                                                                                                                           |
| `debug_logging_enabled`            | boolean                    | false    |              |                                                                                                                                           |
| `hook_allow_insecure`              | boolean                    | false    |              |                                                                                                                                           |
| `hook_enabled`                     | boolean                    | false    |              |                                                                                                                                           |
| `hook_secret`                      | string                     | false    |              |                                                                                                                                           |
| `hook_timeout`                     | integer                    | false    |              |                                                                                                                                           |
| `hook_url`                         | [serpent.URL](#serpenturl) | false    |              |                                                                                                                                           |
| `max_attachments_per_chat`         | integer                    | false    |              | Max attachments per chat is the maximum number of files linked to a chat.                                                                 |
| `max_concurrent_recording_uploads` | integer                    | false    |              | Max concurrent recording uploads is the maximum number of virtual desktop recordings that each Coder server stores at the same time.      |
| `max_generation_retries`           | integer                    | false    |              | Max generation retries is the maximum number of consecutive retries after a model generation fails with a transient error.                |
| `max_prompt_bytes`                 | integer                    | false    |              | Max prompt bytes is the maximum size in bytes of the deployment system prompt, the plan mode instructions, and each user's custom prompt. |
| `max_queued_messages_per_chat`     | integer                    | false    |              | Max queued messages per chat is the maximum number of messages that can be queued in a chat.                                              |
| `max_steps_per_turn`               | integer                    | false    |              | Max steps per turn is the maximum number of steps in a chat turn.                                                                         |
| `stream_silence_timeout`           | integer                    | false    |              |                                                                                                                                           |

## codersdk.ChatContext

```json
{
  "dirty": true,
  "dirty_since": "2019-08-24T14:15:22Z",
  "error": "string",
  "resources": [
    {
      "error": "string",
      "kind": "instruction_file",
      "size_bytes": 0,
      "skill_description": "string",
      "skill_name": "string",
      "source": "string",
      "status": "ok",
      "tools": [
        {
          "description": "string",
          "name": "string"
        }
      ]
    }
  ]
}
```

### Properties

| Name          | Type                                                                  | Required | Restrictions | Description                                                                                                                                                                                                                                |
|---------------|-----------------------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `dirty`       | boolean                                                               | false    |              | Dirty is true when the agent's latest snapshot hash differs from the chat's pinned hash.                                                                                                                                                   |
| `dirty_since` | string                                                                | false    |              | Dirty since is when drift was first detected; nil when not dirty.                                                                                                                                                                          |
| `error`       | string                                                                | false    |              | Error is the snapshot-level error copied from the pinned snapshot (empty when healthy).                                                                                                                                                    |
| `resources`   | array of [codersdk.ChatContextResource](#codersdkchatcontextresource) | false    |              | Resources is the chat's pinned context (instruction files and skills) the prompt is built from, metadata only (no bodies). It is populated only on the single-chat GET response; list and watch payloads leave it nil to stay lightweight. |

## codersdk.ChatContextResource

```json
{
  "error": "string",
  "kind": "instruction_file",
  "size_bytes": 0,
  "skill_description": "string",
  "skill_name": "string",
  "source": "string",
  "status": "ok",
  "tools": [
    {
      "description": "string",
      "name": "string"
    }
  ]
}
```

### Properties

| Name                | Type                                                                     | Required | Restrictions | Description                                                                                                                                                                                                                                                                |
|---------------------|--------------------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `error`             | string                                                                   | false    |              | Error explains a non-ok Status; empty when healthy. May also carry a non-fatal warning when Status is ok.                                                                                                                                                                  |
| `kind`              | [codersdk.ChatContextResourceKind](#codersdkchatcontextresourcekind)     | false    |              |                                                                                                                                                                                                                                                                            |
| `size_bytes`        | integer                                                                  | false    |              | Size bytes is the original payload size in bytes.                                                                                                                                                                                                                          |
| `skill_description` | string                                                                   | false    |              |                                                                                                                                                                                                                                                                            |
| `skill_name`        | string                                                                   | false    |              | Skill name and SkillDescription are populated only for skill kinds.                                                                                                                                                                                                        |
| `source`            | string                                                                   | false    |              | Source is the resource locator: the canonical file path for an instruction file, the skill directory for a skill, the file path for an MCP config, or the server name for an MCP server.                                                                                   |
| `status`            | [codersdk.ChatContextResourceStatus](#codersdkchatcontextresourcestatus) | false    |              | Status is the resource's health. Non-ok resources (invalid, unreadable, oversize, excluded) are still reported so the UI can surface why a resource was dropped from the prompt instead of silently omitting it; their body-specific fields (skill name, tools) are empty. |
| `tools`             | array of [codersdk.ChatContextTool](#codersdkchatcontexttool)            | false    |              | Tools lists the tools exposed by an MCP server. Populated only for the mcp_server kind; nil otherwise.                                                                                                                                                                     |

## codersdk.ChatContextResourceKind

```json
"instruction_file"
```

### Properties

#### Enumerated Values

| Value(s)                                                |
|---------------------------------------------------------|
| `instruction_file`, `mcp_config`, `mcp_server`, `skill` |

## codersdk.ChatContextResourceStatus

```json
"ok"
```

### Properties

#### Enumerated Values

| Value(s)                                              |
|-------------------------------------------------------|
| `excluded`, `invalid`, `ok`, `oversize`, `unreadable` |

## codersdk.ChatContextTool

```json
{
  "description": "string",
  "name": "string"
}
```

### Properties

| Name          | Type   | Required | Restrictions | Description                                                                                                       |
|---------------|--------|----------|--------------|-------------------------------------------------------------------------------------------------------------------|
| `description` | string | false    |              | Description is the tool's human-readable summary; may be empty.                                                   |
| `name`        | string | false    |              | Name is the tool name with the `<server>__` prefix the agent adds stripped, so it reads as the server exposes it. |

## codersdk.ChatCost

```json
{
  "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
  "request_count": 0,
  "total_cost_micros": 0,
  "unpriced_request_count": 0
}
```

### Properties

| Name                     | Type    | Required | Restrictions | Description |
|--------------------------|---------|----------|--------------|-------------|
| `chat_id`                | string  | false    |              |             |
| `request_count`          | integer | false    |              |             |
| `total_cost_micros`      | integer | false    |              |             |
| `unpriced_request_count` | integer | false    |              |             |

## codersdk.ChatDebugLoggingAdminSettings

```json
{
  "allow_users": true,
  "forced_by_deployment": true
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description |
|------------------------|---------|----------|--------------|-------------|
| `allow_users`          | boolean | false    |              |             |
| `forced_by_deployment` | boolean | false    |              |             |

## codersdk.ChatDebugRetentionDaysResponse

```json
{
  "debug_retention_days": 0
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description |
|------------------------|---------|----------|--------------|-------------|
| `debug_retention_days` | integer | false    |              |             |

## codersdk.ChatDiffContents

```json
{
  "branch": "string",
  "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
  "diff": "string",
  "provider": "string",
  "pull_request_url": "string",
  "remote_origin": "string"
}
```

### Properties

| Name               | Type   | Required | Restrictions | Description |
|--------------------|--------|----------|--------------|-------------|
| `branch`           | string | false    |              |             |
| `chat_id`          | string | false    |              |             |
| `diff`             | string | false    |              |             |
| `provider`         | string | false    |              |             |
| `pull_request_url` | string | false    |              |             |
| `remote_origin`    | string | false    |              |             |

## codersdk.ChatDiffStatus

```json
{
  "additions": 0,
  "approved": true,
  "author_avatar_url": "string",
  "author_login": "string",
  "base_branch": "string",
  "changed_files": 0,
  "changes_requested": true,
  "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
  "commits": 0,
  "deletions": 0,
  "head_branch": "string",
  "pr_number": 0,
  "pull_request_draft": true,
  "pull_request_state": "string",
  "pull_request_title": "string",
  "refreshed_at": "2019-08-24T14:15:22Z",
  "reviewer_count": 0,
  "stale_at": "2019-08-24T14:15:22Z",
  "url": "string"
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `additions`          | integer | false    |              |             |
| `approved`           | boolean | false    |              |             |
| `author_avatar_url`  | string  | false    |              |             |
| `author_login`       | string  | false    |              |             |
| `base_branch`        | string  | false    |              |             |
| `changed_files`      | integer | false    |              |             |
| `changes_requested`  | boolean | false    |              |             |
| `chat_id`            | string  | false    |              |             |
| `commits`            | integer | false    |              |             |
| `deletions`          | integer | false    |              |             |
| `head_branch`        | string  | false    |              |             |
| `pr_number`          | integer | false    |              |             |
| `pull_request_draft` | boolean | false    |              |             |
| `pull_request_state` | string  | false    |              |             |
| `pull_request_title` | string  | false    |              |             |
| `refreshed_at`       | string  | false    |              |             |
| `reviewer_count`     | integer | false    |              |             |
| `stale_at`           | string  | false    |              |             |
| `url`                | string  | false    |              |             |

## codersdk.ChatError

```json
{
  "detail": "string",
  "kind": "generic",
  "message": "string",
  "provider": "string",
  "retryable": true,
  "status_code": 0
}
```

### Properties

| Name          | Type                                             | Required | Restrictions | Description                                                                                               |
|---------------|--------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------|
| `detail`      | string                                           | false    |              | Detail is optional provider-specific context shown alongside the normalized error message when available. |
| `kind`        | [codersdk.ChatErrorKind](#codersdkchaterrorkind) | false    |              | Kind classifies the error for consistent client rendering.                                                |
| `message`     | string                                           | false    |              | Message is the normalized, user-facing error message.                                                     |
| `provider`    | string                                           | false    |              | Provider identifies the upstream model provider when known.                                               |
| `retryable`   | boolean                                          | false    |              | Retryable reports whether the underlying error is transient.                                              |
| `status_code` | integer                                          | false    |              | Status code is the best-effort upstream HTTP status code.                                                 |

## codersdk.ChatErrorKind

```json
"generic"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                                                 |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `auth`, `config`, `content_filter`, `generic`, `hook_denied`, `hook_dispatch_failed`, `missing_key`, `overloaded`, `provider_disabled`, `rate_limit`, `stream_silence_timeout`, `timeout`, `usage_limit` |

## codersdk.ChatFileDownloadURLResponse

```json
{
  "expires_at": "2019-08-24T14:15:22Z",
  "mime_type": "string",
  "name": "string",
  "sha256": "string",
  "size_bytes": 0,
  "url": "http://example.com"
}
```

### Properties

| Name         | Type    | Required | Restrictions | Description |
|--------------|---------|----------|--------------|-------------|
| `expires_at` | string  | false    |              |             |
| `mime_type`  | string  | false    |              |             |
| `name`       | string  | false    |              |             |
| `sha256`     | string  | false    |              |             |
| `size_bytes` | integer | false    |              |             |
| `url`        | string  | false    |              |             |

## codersdk.ChatFileMetadata

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "mime_type": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "size_bytes": 0
}
```

### Properties

| Name              | Type    | Required | Restrictions | Description |
|-------------------|---------|----------|--------------|-------------|
| `created_at`      | string  | false    |              |             |
| `id`              | string  | false    |              |             |
| `mime_type`       | string  | false    |              |             |
| `name`            | string  | false    |              |             |
| `organization_id` | string  | false    |              |             |
| `owner_id`        | string  | false    |              |             |
| `size_bytes`      | integer | false    |              |             |

## codersdk.ChatGroup

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "role": "read",
  "source": "user",
  "total_member_count": 0
}
```

### Properties

| Name                        | Type                                                  | Required | Restrictions | Description                                                                                                                                                           |
|-----------------------------|-------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `avatar_url`                | string                                                | false    |              |                                                                                                                                                                       |
| `display_name`              | string                                                | false    |              |                                                                                                                                                                       |
| `id`                        | string                                                | false    |              |                                                                                                                                                                       |
| `members`                   | array of [codersdk.ReducedUser](#codersdkreduceduser) | false    |              |                                                                                                                                                                       |
| `name`                      | string                                                | false    |              |                                                                                                                                                                       |
| `organization_display_name` | string                                                | false    |              |                                                                                                                                                                       |
| `organization_id`           | string                                                | false    |              |                                                                                                                                                                       |
| `organization_name`         | string                                                | false    |              |                                                                                                                                                                       |
| `quota_allowance`           | integer                                               | false    |              |                                                                                                                                                                       |
| `role`                      | [codersdk.ChatRole](#codersdkchatrole)                | false    |              |                                                                                                                                                                       |
| `source`                    | [codersdk.GroupSource](#codersdkgroupsource)          | false    |              |                                                                                                                                                                       |
| `total_member_count`        | integer                                               | false    |              | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. |

#### Enumerated Values

| Property | Value(s) |
|----------|----------|
| `role`   | `read`   |

## codersdk.ChatInputPart

```json
{
  "content": "string",
  "end_line": 0,
  "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  "file_name": "string",
  "start_line": 0,
  "text": "string",
  "type": "text",
  "workspace_file_media_type": "string",
  "workspace_file_name": "string",
  "workspace_file_path": "string",
  "workspace_file_size": 0,
  "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
}
```

### Properties

| Name                          | Type                                                     | Required | Restrictions | Description                                                                                                                                                    |
|-------------------------------|----------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `content`                     | string                                                   | false    |              | The code content from the diff that was commented on.                                                                                                          |
| `end_line`                    | integer                                                  | false    |              |                                                                                                                                                                |
| `file_id`                     | string                                                   | false    |              |                                                                                                                                                                |
| `file_name`                   | string                                                   | false    |              | The following fields are only set when Type is ChatInputPartTypeFileReference.                                                                                 |
| `start_line`                  | integer                                                  | false    |              |                                                                                                                                                                |
| `text`                        | string                                                   | false    |              |                                                                                                                                                                |
| `type`                        | [codersdk.ChatInputPartType](#codersdkchatinputparttype) | false    |              |                                                                                                                                                                |
| `workspace_file_media_type`   | string                                                   | false    |              |                                                                                                                                                                |
| `workspace_file_name`         | string                                                   | false    |              |                                                                                                                                                                |
| `workspace_file_path`         | string                                                   | false    |              | The following fields are only set when Type is ChatInputPartTypeWorkspaceFileReference.                                                                        |
| `workspace_file_size`         | integer                                                  | false    |              |                                                                                                                                                                |
| `workspace_file_workspace_id` | string                                                   | false    |              | Workspace file workspace ID is the workspace the file was uploaded to, as returned by the upload endpoint. It must match the chat's currently bound workspace. |

## codersdk.ChatInputPartType

```json
"text"
```

### Properties

#### Enumerated Values

| Value(s)                                                     |
|--------------------------------------------------------------|
| `file`, `file-reference`, `text`, `workspace-file-reference` |

## codersdk.ChatMessage

```json
{
  "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
  "content": [
    {
      "args": [
        0
      ],
      "args_delta": "string",
      "completed_at": "2019-08-24T14:15:22Z",
      "content": "string",
      "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
      "context_file_content": "string",
      "context_file_directory": "string",
      "context_file_os": "string",
      "context_file_path": "string",
      "context_file_skill_meta_file": "string",
      "context_file_truncated": true,
      "created_at": "2019-08-24T14:15:22Z",
      "data": [
        0
      ],
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "hook_rewritten": true,
      "is_error": true,
      "is_media": true,
      "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
      "media_type": "string",
      "name": "string",
      "parsed_commands": [
        [
          "string"
        ]
      ],
      "provider_executed": true,
      "provider_metadata": [
        0
      ],
      "reasoning_delta": "string",
      "result": [
        0
      ],
      "result_delta": "string",
      "result_reset": true,
      "skill_description": "string",
      "skill_dir": "string",
      "skill_name": "string",
      "source_id": "string",
      "start_line": 0,
      "text": "string",
      "title": "string",
      "tool_call_id": "string",
      "tool_name": "string",
      "type": "text",
      "url": "string",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    }
  ],
  "created_at": "2019-08-24T14:15:22Z",
  "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
  "id": 0,
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
  "queued_message_id": 0,
  "role": "system",
  "usage": {
    "cache_creation_tokens": 0,
    "cache_read_tokens": 0,
    "context_limit": 0,
    "input_tokens": 0,
    "output_tokens": 0,
    "reasoning_tokens": 0,
    "total_tokens": 0
  }
}
```

### Properties

| Name                | Type                                                          | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                     |
|---------------------|---------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `chat_id`           | string                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                 |
| `content`           | array of [codersdk.ChatMessagePart](#codersdkchatmessagepart) | false    |              |                                                                                                                                                                                                                                                                                                                                 |
| `created_at`        | string                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                 |
| `created_by`        | string                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                 |
| `id`                | integer                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                 |
| `model_config_id`   | string                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                 |
| `queued_message_id` | integer                                                       | false    |              | Queued message ID is the ID of the queued message this message was promoted from. It matches ChatQueuedMessage.ID in the response that queued the message. It is nil when the message was not promoted from the queue (edits create a new message without it) or when a server version that did not record the link created it. |
| `role`              | [codersdk.ChatMessageRole](#codersdkchatmessagerole)          | false    |              |                                                                                                                                                                                                                                                                                                                                 |
| `usage`             | [codersdk.ChatMessageUsage](#codersdkchatmessageusage)        | false    |              |                                                                                                                                                                                                                                                                                                                                 |

## codersdk.ChatMessagePart

```json
{
  "args": [
    0
  ],
  "args_delta": "string",
  "completed_at": "2019-08-24T14:15:22Z",
  "content": "string",
  "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
  "context_file_content": "string",
  "context_file_directory": "string",
  "context_file_os": "string",
  "context_file_path": "string",
  "context_file_skill_meta_file": "string",
  "context_file_truncated": true,
  "created_at": "2019-08-24T14:15:22Z",
  "data": [
    0
  ],
  "end_line": 0,
  "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  "file_name": "string",
  "hook_rewritten": true,
  "is_error": true,
  "is_media": true,
  "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
  "media_type": "string",
  "name": "string",
  "parsed_commands": [
    [
      "string"
    ]
  ],
  "provider_executed": true,
  "provider_metadata": [
    0
  ],
  "reasoning_delta": "string",
  "result": [
    0
  ],
  "result_delta": "string",
  "result_reset": true,
  "skill_description": "string",
  "skill_dir": "string",
  "skill_name": "string",
  "source_id": "string",
  "start_line": 0,
  "text": "string",
  "title": "string",
  "tool_call_id": "string",
  "tool_name": "string",
  "type": "text",
  "url": "string",
  "workspace_file_media_type": "string",
  "workspace_file_name": "string",
  "workspace_file_path": "string",
  "workspace_file_size": 0,
  "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
}
```

### Properties

| Name                           | Type                                                         | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                                                                |
|--------------------------------|--------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `args`                         | array of integer                                             | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `args_delta`                   | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `completed_at`                 | string                                                       | false    |              | Completed at is the time a reasoning part finished streaming, so reasoning duration can be computed as completed_at minus created_at. For interrupted reasoning, this is the interruption time. Absent when reasoning timestamp data was not recorded (e.g. messages persisted before this feature was added).                                                                                             |
| `content`                      | string                                                       | false    |              | The code content from the diff that was commented on.                                                                                                                                                                                                                                                                                                                                                      |
| `context_file_agent_id`        | string                                                       | false    |              | Context file agent ID is the workspace agent that provided this context file. Used to detect when the agent changes (e.g. workspace rebuilt) so instruction files can be re-persisted with fresh content.                                                                                                                                                                                                  |
| `context_file_content`         | string                                                       | false    |              | Context file content holds the file content sent to the LLM. Internal only: stripped before API responses to keep payloads small. The backend reads it when building the prompt via partsToMessageParts.                                                                                                                                                                                                   |
| `context_file_directory`       | string                                                       | false    |              | Context file directory is the working directory of the workspace agent. Internal only: same purpose as ContextFileOS.                                                                                                                                                                                                                                                                                      |
| `context_file_os`              | string                                                       | false    |              | Context file os is the operating system of the workspace agent. Internal only: used during prompt expansion so the LLM knows the OS even on turns where InsertSystem is not called.                                                                                                                                                                                                                        |
| `context_file_path`            | string                                                       | false    |              | Context file path is the absolute path of a file loaded into the LLM context (e.g. an AGENTS.md instruction file).                                                                                                                                                                                                                                                                                         |
| `context_file_skill_meta_file` | string                                                       | false    |              | Context file skill meta file is the basename of the skill meta file (e.g. "SKILL.md") at the time of persistence. Internal only: restored on subsequent turns so the read_skill tool uses the correct filename even when the agent configured a non-default value.                                                                                                                                         |
| `context_file_truncated`       | boolean                                                      | false    |              | Context file truncated indicates the file exceeded the 64KiB instruction file limit and was truncated.                                                                                                                                                                                                                                                                                                     |
| `created_at`                   | string                                                       | false    |              | Created at is the timestamp this part carries. The semantics depend on the part type: for tool-call and tool-result parts it is the time the call was emitted or the result was produced (tool duration is the result's created_at minus the call's created_at); for reasoning parts it is the time reasoning started streaming.                                                                           |
| `data`                         | array of integer                                             | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `end_line`                     | integer                                                      | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `file_id`                      | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `file_name`                    | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `hook_rewritten`               | boolean                                                      | false    |              | Hook rewritten indicates that a lifecycle hook replaced model-proposed tool input.                                                                                                                                                                                                                                                                                                                         |
| `is_error`                     | boolean                                                      | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `is_media`                     | boolean                                                      | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `mcp_server_config_id`         | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `media_type`                   | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `name`                         | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `parsed_commands`              | array of array                                               | false    |              | Parsed commands holds parsed programs from an execute tool call's shell command, one entry per simple command in source order. Each entry is [program] or [program, arg] where arg is the first non-flag positional argument. Program names are normalized to their base name (e.g. /usr/bin/go becomes go). Only populated when ToolName is "execute" and the command parses successfully; nil otherwise. |
| `provider_executed`            | boolean                                                      | false    |              | Provider executed indicates the tool call was executed by the provider (e.g. Anthropic computer use).                                                                                                                                                                                                                                                                                                      |
| `provider_metadata`            | array of integer                                             | false    |              | Provider metadata holds provider-specific response metadata (e.g. Anthropic cache control hints) as raw JSON. Internal only: stripped by db2sdk before API responses.                                                                                                                                                                                                                                      |
| `reasoning_delta`              | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `result`                       | array of integer                                             | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `result_delta`                 | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `result_reset`                 | boolean                                                      | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `skill_description`            | string                                                       | false    |              | Skill description is the short description from the skill's SKILL.md frontmatter.                                                                                                                                                                                                                                                                                                                          |
| `skill_dir`                    | string                                                       | false    |              | Skill dir is the absolute path to the skill directory inside the workspace filesystem. Internal only: used by read_skill/read_skill_file tools to locate skill files.                                                                                                                                                                                                                                      |
| `skill_name`                   | string                                                       | false    |              | Skill name is the kebab-case name of a discovered skill from the workspace's .agents/skills/ directory.                                                                                                                                                                                                                                                                                                    |
| `source_id`                    | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `start_line`                   | integer                                                      | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `text`                         | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `title`                        | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `tool_call_id`                 | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `tool_name`                    | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `type`                         | [codersdk.ChatMessagePartType](#codersdkchatmessageparttype) | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `url`                          | string                                                       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                            |
| `workspace_file_media_type`    | string                                                       | false    |              | Workspace file media type is the best-effort declared MIME type.                                                                                                                                                                                                                                                                                                                                           |
| `workspace_file_name`          | string                                                       | false    |              | Workspace file name is the sanitized basename of a workspace upload.                                                                                                                                                                                                                                                                                                                                       |
| `workspace_file_path`          | string                                                       | false    |              | Workspace file path is the absolute path of a workspace upload. The bytes live on the workspace filesystem; only metadata is persisted on the message.                                                                                                                                                                                                                                                     |
| `workspace_file_size`          | integer                                                      | false    |              | Workspace file size is the byte size of a workspace upload.                                                                                                                                                                                                                                                                                                                                                |
| `workspace_file_workspace_id`  | string                                                       | false    |              | Workspace file workspace ID identifies the workspace whose filesystem holds the uploaded bytes. References are only readable while the chat stays bound to that workspace.                                                                                                                                                                                                                                 |

## codersdk.ChatMessagePartType

```json
"text"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `context-file`, `file`, `file-reference`, `hook-context`, `hook-notice`, `reasoning`, `skill`, `source`, `text`, `tool-call`, `tool-result`, `workspace-file-reference` |

## codersdk.ChatMessageRole

```json
"system"
```

### Properties

#### Enumerated Values

| Value(s)                              |
|---------------------------------------|
| `assistant`, `system`, `tool`, `user` |

## codersdk.ChatMessageUsage

```json
{
  "cache_creation_tokens": 0,
  "cache_read_tokens": 0,
  "context_limit": 0,
  "input_tokens": 0,
  "output_tokens": 0,
  "reasoning_tokens": 0,
  "total_tokens": 0
}
```

### Properties

| Name                    | Type    | Required | Restrictions | Description |
|-------------------------|---------|----------|--------------|-------------|
| `cache_creation_tokens` | integer | false    |              |             |
| `cache_read_tokens`     | integer | false    |              |             |
| `context_limit`         | integer | false    |              |             |
| `input_tokens`          | integer | false    |              |             |
| `output_tokens`         | integer | false    |              |             |
| `reasoning_tokens`      | integer | false    |              |             |
| `total_tokens`          | integer | false    |              |             |

## codersdk.ChatMessagesResponse

```json
{
  "has_more": true,
  "messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
      "queued_message_id": 0,
      "role": "system",
      "usage": {
        "cache_creation_tokens": 0,
        "cache_read_tokens": 0,
        "context_limit": 0,
        "input_tokens": 0,
        "output_tokens": 0,
        "reasoning_tokens": 0,
        "total_tokens": 0
      }
    }
  ],
  "queued_messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205"
    }
  ]
}
```

### Properties

| Name              | Type                                                              | Required | Restrictions | Description |
|-------------------|-------------------------------------------------------------------|----------|--------------|-------------|
| `has_more`        | boolean                                                           | false    |              |             |
| `messages`        | array of [codersdk.ChatMessage](#codersdkchatmessage)             | false    |              |             |
| `queued_messages` | array of [codersdk.ChatQueuedMessage](#codersdkchatqueuedmessage) | false    |              |             |

## codersdk.ChatModel

```json
{
  "ai_provider_id": "5a3b8ff9-20e7-4c37-ba1a-5b433e355819",
  "compression_threshold": 0,
  "context_limit": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "display_name": "string",
  "enabled": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_default": true,
  "model": "string",
  "model_config": {
    "frequency_penalty": 0,
    "max_output_tokens": 0,
    "openai_config": {
      "reasoning_model": true,
      "use_responses_api": true
    },
    "presence_penalty": 0,
    "provider_options": {
      "anthropic": {
        "allowed_domains": [
          "string"
        ],
        "blocked_domains": [
          "string"
        ],
        "context_1m_enabled": true,
        "disable_parallel_tool_use": true,
        "send_reasoning": true,
        "thinking": {
          "budget_tokens": 0
        },
        "thinking_display": "string",
        "web_search_enabled": true
      },
      "google": {
        "cached_content": "string",
        "safety_settings": [
          {
            "category": "string",
            "threshold": "string"
          }
        ],
        "thinking_config": {
          "include_thoughts": true,
          "thinking_budget": 0,
          "thinking_level": "string"
        },
        "threshold": "string",
        "web_search_enabled": true
      },
      "openai": {
        "allowed_domains": [
          "string"
        ],
        "include": [
          "string"
        ],
        "instructions": "string",
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "max_completion_tokens": 0,
        "max_tool_calls": 0,
        "metadata": {
          "property1": null,
          "property2": null
        },
        "parallel_tool_calls": true,
        "prediction": {
          "property1": null,
          "property2": null
        },
        "prompt_cache_key": "string",
        "reasoning_mode": "string",
        "reasoning_summary": "string",
        "safety_identifier": "string",
        "search_context_size": "string",
        "service_tier": "string",
        "store": true,
        "strict_json_schema": true,
        "structured_outputs": true,
        "text_verbosity": "string",
        "top_log_probs": 0,
        "user": "string",
        "web_search_enabled": true
      },
      "openaicompat": {
        "user": "string"
      },
      "openrouter": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "include_usage": true,
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "parallel_tool_calls": true,
        "provider": {
          "allow_fallbacks": true,
          "data_collection": "string",
          "ignore": [
            "string"
          ],
          "only": [
            "string"
          ],
          "order": [
            "string"
          ],
          "quantizations": [
            "string"
          ],
          "require_parameters": true,
          "sort": "string"
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "user": "string"
      },
      "vercel": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "logprobs": true,
        "parallel_tool_calls": true,
        "providerOptions": {
          "models": [
            "string"
          ],
          "order": [
            "string"
          ]
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "top_logprobs": 0,
        "user": "string"
      }
    },
    "reasoning_effort": {
      "default": "string",
      "max": "string"
    },
    "temperature": 0,
    "top_k": 0,
    "top_p": 0
  },
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "reasoning_efforts": [
    "string"
  ],
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name                    | Type                                                         | Required | Restrictions | Description                                                                                        |
|-------------------------|--------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------|
| `ai_provider_id`        | string                                                       | false    |              |                                                                                                    |
| `compression_threshold` | integer                                                      | false    |              |                                                                                                    |
| `context_limit`         | integer                                                      | false    |              |                                                                                                    |
| `created_at`            | string                                                       | false    |              |                                                                                                    |
| `display_name`          | string                                                       | false    |              |                                                                                                    |
| `enabled`               | boolean                                                      | false    |              |                                                                                                    |
| `id`                    | string                                                       | false    |              |                                                                                                    |
| `is_default`            | boolean                                                      | false    |              |                                                                                                    |
| `model`                 | string                                                       | false    |              |                                                                                                    |
| `model_config`          | [codersdk.ChatModelCallConfig](#codersdkchatmodelcallconfig) | false    |              |                                                                                                    |
| `organization_id`       | string                                                       | false    |              |                                                                                                    |
| `reasoning_efforts`     | array of string                                              | false    |              | Reasoning efforts lists selectable reasoning effort values through the model's configured maximum. |
| `updated_at`            | string                                                       | false    |              |                                                                                                    |

## codersdk.ChatModelACL

```json
{
  "groups": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "members": [
        {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        }
      ],
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "role": "read",
      "source": "user",
      "total_member_count": 0
    }
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "role": "read",
      "username": "string"
    }
  ]
}
```

### Properties

| Name     | Type                                              | Required | Restrictions | Description |
|----------|---------------------------------------------------|----------|--------------|-------------|
| `groups` | array of [codersdk.ChatGroup](#codersdkchatgroup) | false    |              |             |
| `users`  | array of [codersdk.ChatUser](#codersdkchatuser)   | false    |              |             |

## codersdk.ChatModelAnthropicProviderOptions

```json
{
  "allowed_domains": [
    "string"
  ],
  "blocked_domains": [
    "string"
  ],
  "context_1m_enabled": true,
  "disable_parallel_tool_use": true,
  "send_reasoning": true,
  "thinking": {
    "budget_tokens": 0
  },
  "thinking_display": "string",
  "web_search_enabled": true
}
```

### Properties

| Name                        | Type                                                                                     | Required | Restrictions | Description |
|-----------------------------|------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `allowed_domains`           | array of string                                                                          | false    |              |             |
| `blocked_domains`           | array of string                                                                          | false    |              |             |
| `context_1m_enabled`        | boolean                                                                                  | false    |              |             |
| `disable_parallel_tool_use` | boolean                                                                                  | false    |              |             |
| `send_reasoning`            | boolean                                                                                  | false    |              |             |
| `thinking`                  | [codersdk.ChatModelAnthropicThinkingOptions](#codersdkchatmodelanthropicthinkingoptions) | false    |              |             |
| `thinking_display`          | string                                                                                   | false    |              |             |
| `web_search_enabled`        | boolean                                                                                  | false    |              |             |

## codersdk.ChatModelAnthropicThinkingOptions

```json
{
  "budget_tokens": 0
}
```

### Properties

| Name            | Type    | Required | Restrictions | Description |
|-----------------|---------|----------|--------------|-------------|
| `budget_tokens` | integer | false    |              |             |

## codersdk.ChatModelCallConfig

```json
{
  "frequency_penalty": 0,
  "max_output_tokens": 0,
  "openai_config": {
    "reasoning_model": true,
    "use_responses_api": true
  },
  "presence_penalty": 0,
  "provider_options": {
    "anthropic": {
      "allowed_domains": [
        "string"
      ],
      "blocked_domains": [
        "string"
      ],
      "context_1m_enabled": true,
      "disable_parallel_tool_use": true,
      "send_reasoning": true,
      "thinking": {
        "budget_tokens": 0
      },
      "thinking_display": "string",
      "web_search_enabled": true
    },
    "google": {
      "cached_content": "string",
      "safety_settings": [
        {
          "category": "string",
          "threshold": "string"
        }
      ],
      "thinking_config": {
        "include_thoughts": true,
        "thinking_budget": 0,
        "thinking_level": "string"
      },
      "threshold": "string",
      "web_search_enabled": true
    },
    "openai": {
      "allowed_domains": [
        "string"
      ],
      "include": [
        "string"
      ],
      "instructions": "string",
      "log_probs": true,
      "logit_bias": {
        "property1": 0,
        "property2": 0
      },
      "max_completion_tokens": 0,
      "max_tool_calls": 0,
      "metadata": {
        "property1": null,
        "property2": null
      },
      "parallel_tool_calls": true,
      "prediction": {
        "property1": null,
        "property2": null
      },
      "prompt_cache_key": "string",
      "reasoning_mode": "string",
      "reasoning_summary": "string",
      "safety_identifier": "string",
      "search_context_size": "string",
      "service_tier": "string",
      "store": true,
      "strict_json_schema": true,
      "structured_outputs": true,
      "text_verbosity": "string",
      "top_log_probs": 0,
      "user": "string",
      "web_search_enabled": true
    },
    "openaicompat": {
      "user": "string"
    },
    "openrouter": {
      "extra_body": {
        "property1": null,
        "property2": null
      },
      "include_usage": true,
      "log_probs": true,
      "logit_bias": {
        "property1": 0,
        "property2": 0
      },
      "parallel_tool_calls": true,
      "provider": {
        "allow_fallbacks": true,
        "data_collection": "string",
        "ignore": [
          "string"
        ],
        "only": [
          "string"
        ],
        "order": [
          "string"
        ],
        "quantizations": [
          "string"
        ],
        "require_parameters": true,
        "sort": "string"
      },
      "reasoning": {
        "enabled": true,
        "exclude": true,
        "max_tokens": 0
      },
      "user": "string"
    },
    "vercel": {
      "extra_body": {
        "property1": null,
        "property2": null
      },
      "logit_bias": {
        "property1": 0,
        "property2": 0
      },
      "logprobs": true,
      "parallel_tool_calls": true,
      "providerOptions": {
        "models": [
          "string"
        ],
        "order": [
          "string"
        ]
      },
      "reasoning": {
        "enabled": true,
        "exclude": true,
        "max_tokens": 0
      },
      "top_logprobs": 0,
      "user": "string"
    }
  },
  "reasoning_effort": {
    "default": "string",
    "max": "string"
  },
  "temperature": 0,
  "top_k": 0,
  "top_p": 0
}
```

### Properties

| Name                | Type                                                                               | Required | Restrictions | Description |
|---------------------|------------------------------------------------------------------------------------|----------|--------------|-------------|
| `frequency_penalty` | number                                                                             | false    |              |             |
| `max_output_tokens` | integer                                                                            | false    |              |             |
| `openai_config`     | [codersdk.ChatModelOpenAIConfig](#codersdkchatmodelopenaiconfig)                   | false    |              |             |
| `presence_penalty`  | number                                                                             | false    |              |             |
| `provider_options`  | [codersdk.ChatModelProviderOptions](#codersdkchatmodelprovideroptions)             | false    |              |             |
| `reasoning_effort`  | [codersdk.ChatModelReasoningEffortConfig](#codersdkchatmodelreasoningeffortconfig) | false    |              |             |
| `temperature`       | number                                                                             | false    |              |             |
| `top_k`             | integer                                                                            | false    |              |             |
| `top_p`             | number                                                                             | false    |              |             |

## codersdk.ChatModelGoogleProviderOptions

```json
{
  "cached_content": "string",
  "safety_settings": [
    {
      "category": "string",
      "threshold": "string"
    }
  ],
  "thinking_config": {
    "include_thoughts": true,
    "thinking_budget": 0,
    "thinking_level": "string"
  },
  "threshold": "string",
  "web_search_enabled": true
}
```

### Properties

| Name                 | Type                                                                                    | Required | Restrictions | Description |
|----------------------|-----------------------------------------------------------------------------------------|----------|--------------|-------------|
| `cached_content`     | string                                                                                  | false    |              |             |
| `safety_settings`    | array of [codersdk.ChatModelGoogleSafetySetting](#codersdkchatmodelgooglesafetysetting) | false    |              |             |
| `thinking_config`    | [codersdk.ChatModelGoogleThinkingConfig](#codersdkchatmodelgooglethinkingconfig)        | false    |              |             |
| `threshold`          | string                                                                                  | false    |              |             |
| `web_search_enabled` | boolean                                                                                 | false    |              |             |

## codersdk.ChatModelGoogleSafetySetting

```json
{
  "category": "string",
  "threshold": "string"
}
```

### Properties

| Name        | Type   | Required | Restrictions | Description |
|-------------|--------|----------|--------------|-------------|
| `category`  | string | false    |              |             |
| `threshold` | string | false    |              |             |

## codersdk.ChatModelGoogleThinkingConfig

```json
{
  "include_thoughts": true,
  "thinking_budget": 0,
  "thinking_level": "string"
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description |
|--------------------|---------|----------|--------------|-------------|
| `include_thoughts` | boolean | false    |              |             |
| `thinking_budget`  | integer | false    |              |             |
| `thinking_level`   | string  | false    |              |             |

## codersdk.ChatModelOpenAICompatProviderOptions

```json
{
  "user": "string"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description |
|--------|--------|----------|--------------|-------------|
| `user` | string | false    |              |             |

## codersdk.ChatModelOpenAIConfig

```json
{
  "reasoning_model": true,
  "use_responses_api": true
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `reasoning_model`   | boolean | false    |              |             |
| `use_responses_api` | boolean | false    |              |             |

## codersdk.ChatModelOpenAIProviderOptions

```json
{
  "allowed_domains": [
    "string"
  ],
  "include": [
    "string"
  ],
  "instructions": "string",
  "log_probs": true,
  "logit_bias": {
    "property1": 0,
    "property2": 0
  },
  "max_completion_tokens": 0,
  "max_tool_calls": 0,
  "metadata": {
    "property1": null,
    "property2": null
  },
  "parallel_tool_calls": true,
  "prediction": {
    "property1": null,
    "property2": null
  },
  "prompt_cache_key": "string",
  "reasoning_mode": "string",
  "reasoning_summary": "string",
  "safety_identifier": "string",
  "search_context_size": "string",
  "service_tier": "string",
  "store": true,
  "strict_json_schema": true,
  "structured_outputs": true,
  "text_verbosity": "string",
  "top_log_probs": 0,
  "user": "string",
  "web_search_enabled": true
}
```

### Properties

| Name                    | Type            | Required | Restrictions | Description |
|-------------------------|-----------------|----------|--------------|-------------|
| `allowed_domains`       | array of string | false    |              |             |
| `include`               | array of string | false    |              |             |
| `instructions`          | string          | false    |              |             |
| `log_probs`             | boolean         | false    |              |             |
| `logit_bias`            | object          | false    |              |             |
| » `[any property]`      | integer         | false    |              |             |
| `max_completion_tokens` | integer         | false    |              |             |
| `max_tool_calls`        | integer         | false    |              |             |
| `metadata`              | object          | false    |              |             |
| » `[any property]`      | any             | false    |              |             |
| `parallel_tool_calls`   | boolean         | false    |              |             |
| `prediction`            | object          | false    |              |             |
| » `[any property]`      | any             | false    |              |             |
| `prompt_cache_key`      | string          | false    |              |             |
| `reasoning_mode`        | string          | false    |              |             |
| `reasoning_summary`     | string          | false    |              |             |
| `safety_identifier`     | string          | false    |              |             |
| `search_context_size`   | string          | false    |              |             |
| `service_tier`          | string          | false    |              |             |
| `store`                 | boolean         | false    |              |             |
| `strict_json_schema`    | boolean         | false    |              |             |
| `structured_outputs`    | boolean         | false    |              |             |
| `text_verbosity`        | string          | false    |              |             |
| `top_log_probs`         | integer         | false    |              |             |
| `user`                  | string          | false    |              |             |
| `web_search_enabled`    | boolean         | false    |              |             |

## codersdk.ChatModelOpenRouterProvider

```json
{
  "allow_fallbacks": true,
  "data_collection": "string",
  "ignore": [
    "string"
  ],
  "only": [
    "string"
  ],
  "order": [
    "string"
  ],
  "quantizations": [
    "string"
  ],
  "require_parameters": true,
  "sort": "string"
}
```

### Properties

| Name                 | Type            | Required | Restrictions | Description |
|----------------------|-----------------|----------|--------------|-------------|
| `allow_fallbacks`    | boolean         | false    |              |             |
| `data_collection`    | string          | false    |              |             |
| `ignore`             | array of string | false    |              |             |
| `only`               | array of string | false    |              |             |
| `order`              | array of string | false    |              |             |
| `quantizations`      | array of string | false    |              |             |
| `require_parameters` | boolean         | false    |              |             |
| `sort`               | string          | false    |              |             |

## codersdk.ChatModelOpenRouterProviderOptions

```json
{
  "extra_body": {
    "property1": null,
    "property2": null
  },
  "include_usage": true,
  "log_probs": true,
  "logit_bias": {
    "property1": 0,
    "property2": 0
  },
  "parallel_tool_calls": true,
  "provider": {
    "allow_fallbacks": true,
    "data_collection": "string",
    "ignore": [
      "string"
    ],
    "only": [
      "string"
    ],
    "order": [
      "string"
    ],
    "quantizations": [
      "string"
    ],
    "require_parameters": true,
    "sort": "string"
  },
  "reasoning": {
    "enabled": true,
    "exclude": true,
    "max_tokens": 0
  },
  "user": "string"
}
```

### Properties

| Name                  | Type                                                                         | Required | Restrictions | Description |
|-----------------------|------------------------------------------------------------------------------|----------|--------------|-------------|
| `extra_body`          | object                                                                       | false    |              |             |
| » `[any property]`    | any                                                                          | false    |              |             |
| `include_usage`       | boolean                                                                      | false    |              |             |
| `log_probs`           | boolean                                                                      | false    |              |             |
| `logit_bias`          | object                                                                       | false    |              |             |
| » `[any property]`    | integer                                                                      | false    |              |             |
| `parallel_tool_calls` | boolean                                                                      | false    |              |             |
| `provider`            | [codersdk.ChatModelOpenRouterProvider](#codersdkchatmodelopenrouterprovider) | false    |              |             |
| `reasoning`           | [codersdk.ChatModelReasoningOptions](#codersdkchatmodelreasoningoptions)     | false    |              |             |
| `user`                | string                                                                       | false    |              |             |

## codersdk.ChatModelOverrideContext

```json
"general"
```

### Properties

#### Enumerated Values

| Value(s)                                                          |
|-------------------------------------------------------------------|
| `advisor`, `compaction`, `explore`, `general`, `title_generation` |

## codersdk.ChatModelOverrideResponse

```json
{
  "context": "general",
  "model_config_id": "string",
  "reasoning_effort": "string"
}
```

### Properties

| Name               | Type                                                                   | Required | Restrictions | Description |
|--------------------|------------------------------------------------------------------------|----------|--------------|-------------|
| `context`          | [codersdk.ChatModelOverrideContext](#codersdkchatmodeloverridecontext) | false    |              |             |
| `model_config_id`  | string                                                                 | false    |              |             |
| `reasoning_effort` | string                                                                 | false    |              |             |

## codersdk.ChatModelOverridesResponse

```json
{
  "overrides": [
    {
      "context": "general",
      "model_config_id": "string",
      "reasoning_effort": "string"
    }
  ]
}
```

### Properties

| Name        | Type                                                                              | Required | Restrictions | Description |
|-------------|-----------------------------------------------------------------------------------|----------|--------------|-------------|
| `overrides` | array of [codersdk.ChatModelOverrideResponse](#codersdkchatmodeloverrideresponse) | false    |              |             |

## codersdk.ChatModelProviderDescriptor

```json
{
  "allow_user_api_key": true,
  "available": true,
  "display_name": "string",
  "enabled": true,
  "has_api_key": true,
  "has_effective_api_key": true,
  "has_user_api_key": true,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "type": "string",
  "unavailable_reason": "missing_api_key"
}
```

### Properties

| Name                    | Type                                                                                       | Required | Restrictions | Description |
|-------------------------|--------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `allow_user_api_key`    | boolean                                                                                    | false    |              |             |
| `available`             | boolean                                                                                    | false    |              |             |
| `display_name`          | string                                                                                     | false    |              |             |
| `enabled`               | boolean                                                                                    | false    |              |             |
| `has_api_key`           | boolean                                                                                    | false    |              |             |
| `has_effective_api_key` | boolean                                                                                    | false    |              |             |
| `has_user_api_key`      | boolean                                                                                    | false    |              |             |
| `icon`                  | string                                                                                     | false    |              |             |
| `id`                    | string                                                                                     | false    |              |             |
| `type`                  | string                                                                                     | false    |              |             |
| `unavailable_reason`    | [codersdk.ChatModelProviderUnavailableReason](#codersdkchatmodelproviderunavailablereason) | false    |              |             |

## codersdk.ChatModelProviderOptions

```json
{
  "anthropic": {
    "allowed_domains": [
      "string"
    ],
    "blocked_domains": [
      "string"
    ],
    "context_1m_enabled": true,
    "disable_parallel_tool_use": true,
    "send_reasoning": true,
    "thinking": {
      "budget_tokens": 0
    },
    "thinking_display": "string",
    "web_search_enabled": true
  },
  "google": {
    "cached_content": "string",
    "safety_settings": [
      {
        "category": "string",
        "threshold": "string"
      }
    ],
    "thinking_config": {
      "include_thoughts": true,
      "thinking_budget": 0,
      "thinking_level": "string"
    },
    "threshold": "string",
    "web_search_enabled": true
  },
  "openai": {
    "allowed_domains": [
      "string"
    ],
    "include": [
      "string"
    ],
    "instructions": "string",
    "log_probs": true,
    "logit_bias": {
      "property1": 0,
      "property2": 0
    },
    "max_completion_tokens": 0,
    "max_tool_calls": 0,
    "metadata": {
      "property1": null,
      "property2": null
    },
    "parallel_tool_calls": true,
    "prediction": {
      "property1": null,
      "property2": null
    },
    "prompt_cache_key": "string",
    "reasoning_mode": "string",
    "reasoning_summary": "string",
    "safety_identifier": "string",
    "search_context_size": "string",
    "service_tier": "string",
    "store": true,
    "strict_json_schema": true,
    "structured_outputs": true,
    "text_verbosity": "string",
    "top_log_probs": 0,
    "user": "string",
    "web_search_enabled": true
  },
  "openaicompat": {
    "user": "string"
  },
  "openrouter": {
    "extra_body": {
      "property1": null,
      "property2": null
    },
    "include_usage": true,
    "log_probs": true,
    "logit_bias": {
      "property1": 0,
      "property2": 0
    },
    "parallel_tool_calls": true,
    "provider": {
      "allow_fallbacks": true,
      "data_collection": "string",
      "ignore": [
        "string"
      ],
      "only": [
        "string"
      ],
      "order": [
        "string"
      ],
      "quantizations": [
        "string"
      ],
      "require_parameters": true,
      "sort": "string"
    },
    "reasoning": {
      "enabled": true,
      "exclude": true,
      "max_tokens": 0
    },
    "user": "string"
  },
  "vercel": {
    "extra_body": {
      "property1": null,
      "property2": null
    },
    "logit_bias": {
      "property1": 0,
      "property2": 0
    },
    "logprobs": true,
    "parallel_tool_calls": true,
    "providerOptions": {
      "models": [
        "string"
      ],
      "order": [
        "string"
      ]
    },
    "reasoning": {
      "enabled": true,
      "exclude": true,
      "max_tokens": 0
    },
    "top_logprobs": 0,
    "user": "string"
  }
}
```

### Properties

| Name           | Type                                                                                           | Required | Restrictions | Description |
|----------------|------------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `anthropic`    | [codersdk.ChatModelAnthropicProviderOptions](#codersdkchatmodelanthropicprovideroptions)       | false    |              |             |
| `google`       | [codersdk.ChatModelGoogleProviderOptions](#codersdkchatmodelgoogleprovideroptions)             | false    |              |             |
| `openai`       | [codersdk.ChatModelOpenAIProviderOptions](#codersdkchatmodelopenaiprovideroptions)             | false    |              |             |
| `openaicompat` | [codersdk.ChatModelOpenAICompatProviderOptions](#codersdkchatmodelopenaicompatprovideroptions) | false    |              |             |
| `openrouter`   | [codersdk.ChatModelOpenRouterProviderOptions](#codersdkchatmodelopenrouterprovideroptions)     | false    |              |             |
| `vercel`       | [codersdk.ChatModelVercelProviderOptions](#codersdkchatmodelvercelprovideroptions)             | false    |              |             |

## codersdk.ChatModelProviderUnavailableReason

```json
"missing_api_key"
```

### Properties

#### Enumerated Values

| Value(s)                                                   |
|------------------------------------------------------------|
| `fetch_failed`, `missing_api_key`, `user_api_key_required` |

## codersdk.ChatModelReasoningEffortConfig

```json
{
  "default": "string",
  "max": "string"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description |
|-----------|--------|----------|--------------|-------------|
| `default` | string | false    |              |             |
| `max`     | string | false    |              |             |

## codersdk.ChatModelReasoningOptions

```json
{
  "enabled": true,
  "exclude": true,
  "max_tokens": 0
}
```

### Properties

| Name         | Type    | Required | Restrictions | Description |
|--------------|---------|----------|--------------|-------------|
| `enabled`    | boolean | false    |              |             |
| `exclude`    | boolean | false    |              |             |
| `max_tokens` | integer | false    |              |             |

## codersdk.ChatModelVercelGatewayProviderOptions

```json
{
  "models": [
    "string"
  ],
  "order": [
    "string"
  ]
}
```

### Properties

| Name     | Type            | Required | Restrictions | Description |
|----------|-----------------|----------|--------------|-------------|
| `models` | array of string | false    |              |             |
| `order`  | array of string | false    |              |             |

## codersdk.ChatModelVercelProviderOptions

```json
{
  "extra_body": {
    "property1": null,
    "property2": null
  },
  "logit_bias": {
    "property1": 0,
    "property2": 0
  },
  "logprobs": true,
  "parallel_tool_calls": true,
  "providerOptions": {
    "models": [
      "string"
    ],
    "order": [
      "string"
    ]
  },
  "reasoning": {
    "enabled": true,
    "exclude": true,
    "max_tokens": 0
  },
  "top_logprobs": 0,
  "user": "string"
}
```

### Properties

| Name                  | Type                                                                                             | Required | Restrictions | Description |
|-----------------------|--------------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `extra_body`          | object                                                                                           | false    |              |             |
| » `[any property]`    | any                                                                                              | false    |              |             |
| `logit_bias`          | object                                                                                           | false    |              |             |
| » `[any property]`    | integer                                                                                          | false    |              |             |
| `logprobs`            | boolean                                                                                          | false    |              |             |
| `parallel_tool_calls` | boolean                                                                                          | false    |              |             |
| `providerOptions`     | [codersdk.ChatModelVercelGatewayProviderOptions](#codersdkchatmodelvercelgatewayprovideroptions) | false    |              |             |
| `reasoning`           | [codersdk.ChatModelReasoningOptions](#codersdkchatmodelreasoningoptions)                         | false    |              |             |
| `top_logprobs`        | integer                                                                                          | false    |              |             |
| `user`                | string                                                                                           | false    |              |             |

## codersdk.ChatPersonalModelOverride

```json
{
  "context": "root",
  "is_set": true,
  "mode": "deployment_default",
  "model_config_id": "string",
  "reasoning_effort": "string"
}
```

### Properties

| Name               | Type                                                                                   | Required | Restrictions | Description |
|--------------------|----------------------------------------------------------------------------------------|----------|--------------|-------------|
| `context`          | [codersdk.ChatPersonalModelOverrideContext](#codersdkchatpersonalmodeloverridecontext) | false    |              |             |
| `is_set`           | boolean                                                                                | false    |              |             |
| `mode`             | [codersdk.ChatPersonalModelOverrideMode](#codersdkchatpersonalmodeloverridemode)       | false    |              |             |
| `model_config_id`  | string                                                                                 | false    |              |             |
| `reasoning_effort` | string                                                                                 | false    |              |             |

## codersdk.ChatPersonalModelOverrideContext

```json
"root"
```

### Properties

#### Enumerated Values

| Value(s)                     |
|------------------------------|
| `explore`, `general`, `root` |

## codersdk.ChatPersonalModelOverrideDeploymentDefaults

```json
{
  "explore": {
    "context": "general",
    "model_config_id": "string",
    "reasoning_effort": "string"
  },
  "general": {
    "context": "general",
    "model_config_id": "string",
    "reasoning_effort": "string"
  }
}
```

### Properties

| Name      | Type                                                                     | Required | Restrictions | Description |
|-----------|--------------------------------------------------------------------------|----------|--------------|-------------|
| `explore` | [codersdk.ChatModelOverrideResponse](#codersdkchatmodeloverrideresponse) | false    |              |             |
| `general` | [codersdk.ChatModelOverrideResponse](#codersdkchatmodeloverrideresponse) | false    |              |             |

## codersdk.ChatPersonalModelOverrideMode

```json
"deployment_default"
```

### Properties

#### Enumerated Values

| Value(s)                                      |
|-----------------------------------------------|
| `chat_default`, `deployment_default`, `model` |

## codersdk.ChatPersonalModelOverridesAdminSettings

```json
{
  "allow_users": true
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `allow_users` | boolean | false    |              |             |

## codersdk.ChatPlanMode

```json
"plan"
```

### Properties

#### Enumerated Values

| Value(s) |
|----------|
| `plan`   |

## codersdk.ChatPlanModeInstructionsResponse

```json
{
  "plan_mode_instructions": "string"
}
```

### Properties

| Name                     | Type   | Required | Restrictions | Description |
|--------------------------|--------|----------|--------------|-------------|
| `plan_mode_instructions` | string | false    |              |             |

## codersdk.ChatPrompt

```json
{
  "id": 0,
  "text": "string"
}
```

### Properties

| Name   | Type    | Required | Restrictions | Description |
|--------|---------|----------|--------------|-------------|
| `id`   | integer | false    |              |             |
| `text` | string  | false    |              |             |

## codersdk.ChatPromptsResponse

```json
{
  "prompts": [
    {
      "id": 0,
      "text": "string"
    }
  ]
}
```

### Properties

| Name      | Type                                                | Required | Restrictions | Description |
|-----------|-----------------------------------------------------|----------|--------------|-------------|
| `prompts` | array of [codersdk.ChatPrompt](#codersdkchatprompt) | false    |              |             |

## codersdk.ChatQueuedMessage

```json
{
  "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
  "content": [
    {
      "args": [
        0
      ],
      "args_delta": "string",
      "completed_at": "2019-08-24T14:15:22Z",
      "content": "string",
      "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
      "context_file_content": "string",
      "context_file_directory": "string",
      "context_file_os": "string",
      "context_file_path": "string",
      "context_file_skill_meta_file": "string",
      "context_file_truncated": true,
      "created_at": "2019-08-24T14:15:22Z",
      "data": [
        0
      ],
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "hook_rewritten": true,
      "is_error": true,
      "is_media": true,
      "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
      "media_type": "string",
      "name": "string",
      "parsed_commands": [
        [
          "string"
        ]
      ],
      "provider_executed": true,
      "provider_metadata": [
        0
      ],
      "reasoning_delta": "string",
      "result": [
        0
      ],
      "result_delta": "string",
      "result_reset": true,
      "skill_description": "string",
      "skill_dir": "string",
      "skill_name": "string",
      "source_id": "string",
      "start_line": 0,
      "text": "string",
      "title": "string",
      "tool_call_id": "string",
      "tool_name": "string",
      "type": "text",
      "url": "string",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    }
  ],
  "created_at": "2019-08-24T14:15:22Z",
  "id": 0,
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205"
}
```

### Properties

| Name              | Type                                                          | Required | Restrictions | Description |
|-------------------|---------------------------------------------------------------|----------|--------------|-------------|
| `chat_id`         | string                                                        | false    |              |             |
| `content`         | array of [codersdk.ChatMessagePart](#codersdkchatmessagepart) | false    |              |             |
| `created_at`      | string                                                        | false    |              |             |
| `id`              | integer                                                       | false    |              |             |
| `model_config_id` | string                                                        | false    |              |             |

## codersdk.ChatRetentionDaysResponse

```json
{
  "retention_days": 0
}
```

### Properties

| Name             | Type    | Required | Restrictions | Description |
|------------------|---------|----------|--------------|-------------|
| `retention_days` | integer | false    |              |             |

## codersdk.ChatRole

```json
"read"
```

### Properties

#### Enumerated Values

| Value(s)   |
|------------|
| ``, `read` |

## codersdk.ChatStatus

```json
"waiting"
```

### Properties

#### Enumerated Values

| Value(s)                                                         |
|------------------------------------------------------------------|
| `error`, `interrupting`, `requires_action`, `running`, `waiting` |

## codersdk.ChatStreamActionRequired

```json
{
  "tool_calls": [
    {
      "args": "string",
      "tool_call_id": "string",
      "tool_name": "string"
    }
  ]
}
```

### Properties

| Name         | Type                                                                | Required | Restrictions | Description |
|--------------|---------------------------------------------------------------------|----------|--------------|-------------|
| `tool_calls` | array of [codersdk.ChatStreamToolCall](#codersdkchatstreamtoolcall) | false    |              |             |

## codersdk.ChatStreamEvent

```json
{
  "action_required": {
    "tool_calls": [
      {
        "args": "string",
        "tool_call_id": "string",
        "tool_name": "string"
      }
    ]
  },
  "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
  "error": {
    "detail": "string",
    "kind": "generic",
    "message": "string",
    "provider": "string",
    "retryable": true,
    "status_code": 0
  },
  "message": {
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "content": [
      {
        "args": [
          0
        ],
        "args_delta": "string",
        "completed_at": "2019-08-24T14:15:22Z",
        "content": "string",
        "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
        "context_file_content": "string",
        "context_file_directory": "string",
        "context_file_os": "string",
        "context_file_path": "string",
        "context_file_skill_meta_file": "string",
        "context_file_truncated": true,
        "created_at": "2019-08-24T14:15:22Z",
        "data": [
          0
        ],
        "end_line": 0,
        "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
        "file_name": "string",
        "hook_rewritten": true,
        "is_error": true,
        "is_media": true,
        "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
        "media_type": "string",
        "name": "string",
        "parsed_commands": [
          [
            "string"
          ]
        ],
        "provider_executed": true,
        "provider_metadata": [
          0
        ],
        "reasoning_delta": "string",
        "result": [
          0
        ],
        "result_delta": "string",
        "result_reset": true,
        "skill_description": "string",
        "skill_dir": "string",
        "skill_name": "string",
        "source_id": "string",
        "start_line": 0,
        "text": "string",
        "title": "string",
        "tool_call_id": "string",
        "tool_name": "string",
        "type": "text",
        "url": "string",
        "workspace_file_media_type": "string",
        "workspace_file_name": "string",
        "workspace_file_path": "string",
        "workspace_file_size": 0,
        "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
    "id": 0,
    "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
    "queued_message_id": 0,
    "role": "system",
    "usage": {
      "cache_creation_tokens": 0,
      "cache_read_tokens": 0,
      "context_limit": 0,
      "input_tokens": 0,
      "output_tokens": 0,
      "reasoning_tokens": 0,
      "total_tokens": 0
    }
  },
  "message_part": {
    "generation_attempt": 0,
    "history_version": 0,
    "part": {
      "args": [
        0
      ],
      "args_delta": "string",
      "completed_at": "2019-08-24T14:15:22Z",
      "content": "string",
      "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
      "context_file_content": "string",
      "context_file_directory": "string",
      "context_file_os": "string",
      "context_file_path": "string",
      "context_file_skill_meta_file": "string",
      "context_file_truncated": true,
      "created_at": "2019-08-24T14:15:22Z",
      "data": [
        0
      ],
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "hook_rewritten": true,
      "is_error": true,
      "is_media": true,
      "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
      "media_type": "string",
      "name": "string",
      "parsed_commands": [
        [
          "string"
        ]
      ],
      "provider_executed": true,
      "provider_metadata": [
        0
      ],
      "reasoning_delta": "string",
      "result": [
        0
      ],
      "result_delta": "string",
      "result_reset": true,
      "skill_description": "string",
      "skill_dir": "string",
      "skill_name": "string",
      "source_id": "string",
      "start_line": 0,
      "text": "string",
      "title": "string",
      "tool_call_id": "string",
      "tool_name": "string",
      "type": "text",
      "url": "string",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    },
    "role": "system",
    "seq": 0
  },
  "queued_messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205"
    }
  ],
  "retry": {
    "attempt": 0,
    "delay_ms": 0,
    "error": "string",
    "kind": "generic",
    "provider": "string",
    "retrying_at": "2019-08-24T14:15:22Z",
    "status_code": 0
  },
  "status": {
    "status": "waiting"
  },
  "type": "message_part"
}
```

### Properties

| Name              | Type                                                                   | Required | Restrictions | Description |
|-------------------|------------------------------------------------------------------------|----------|--------------|-------------|
| `action_required` | [codersdk.ChatStreamActionRequired](#codersdkchatstreamactionrequired) | false    |              |             |
| `chat_id`         | string                                                                 | false    |              |             |
| `error`           | [codersdk.ChatError](#codersdkchaterror)                               | false    |              |             |
| `message`         | [codersdk.ChatMessage](#codersdkchatmessage)                           | false    |              |             |
| `message_part`    | [codersdk.ChatStreamMessagePart](#codersdkchatstreammessagepart)       | false    |              |             |
| `queued_messages` | array of [codersdk.ChatQueuedMessage](#codersdkchatqueuedmessage)      | false    |              |             |
| `retry`           | [codersdk.ChatStreamRetry](#codersdkchatstreamretry)                   | false    |              |             |
| `status`          | [codersdk.ChatStreamStatus](#codersdkchatstreamstatus)                 | false    |              |             |
| `type`            | [codersdk.ChatStreamEventType](#codersdkchatstreameventtype)           | false    |              |             |

## codersdk.ChatStreamEventType

```json
"message_part"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                   |
|----------------------------------------------------------------------------------------------------------------------------|
| `action_required`, `error`, `history_reset`, `message`, `message_part`, `preview_reset`, `queue_update`, `retry`, `status` |

## codersdk.ChatStreamMessagePart

```json
{
  "generation_attempt": 0,
  "history_version": 0,
  "part": {
    "args": [
      0
    ],
    "args_delta": "string",
    "completed_at": "2019-08-24T14:15:22Z",
    "content": "string",
    "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
    "context_file_content": "string",
    "context_file_directory": "string",
    "context_file_os": "string",
    "context_file_path": "string",
    "context_file_skill_meta_file": "string",
    "context_file_truncated": true,
    "created_at": "2019-08-24T14:15:22Z",
    "data": [
      0
    ],
    "end_line": 0,
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "file_name": "string",
    "hook_rewritten": true,
    "is_error": true,
    "is_media": true,
    "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
    "media_type": "string",
    "name": "string",
    "parsed_commands": [
      [
        "string"
      ]
    ],
    "provider_executed": true,
    "provider_metadata": [
      0
    ],
    "reasoning_delta": "string",
    "result": [
      0
    ],
    "result_delta": "string",
    "result_reset": true,
    "skill_description": "string",
    "skill_dir": "string",
    "skill_name": "string",
    "source_id": "string",
    "start_line": 0,
    "text": "string",
    "title": "string",
    "tool_call_id": "string",
    "tool_name": "string",
    "type": "text",
    "url": "string",
    "workspace_file_media_type": "string",
    "workspace_file_name": "string",
    "workspace_file_path": "string",
    "workspace_file_size": 0,
    "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
  },
  "role": "system",
  "seq": 0
}
```

### Properties

| Name                 | Type                                                 | Required | Restrictions | Description |
|----------------------|------------------------------------------------------|----------|--------------|-------------|
| `generation_attempt` | integer                                              | false    |              |             |
| `history_version`    | integer                                              | false    |              |             |
| `part`               | [codersdk.ChatMessagePart](#codersdkchatmessagepart) | false    |              |             |
| `role`               | [codersdk.ChatMessageRole](#codersdkchatmessagerole) | false    |              |             |
| `seq`                | integer                                              | false    |              |             |

## codersdk.ChatStreamRetry

```json
{
  "attempt": 0,
  "delay_ms": 0,
  "error": "string",
  "kind": "generic",
  "provider": "string",
  "retrying_at": "2019-08-24T14:15:22Z",
  "status_code": 0
}
```

### Properties

| Name          | Type                                             | Required | Restrictions | Description                                                       |
|---------------|--------------------------------------------------|----------|--------------|-------------------------------------------------------------------|
| `attempt`     | integer                                          | false    |              | Attempt is the 1-indexed retry attempt number.                    |
| `delay_ms`    | integer                                          | false    |              | Delay ms is the backoff delay in milliseconds before the retry.   |
| `error`       | string                                           | false    |              | Error is the normalized error message from the failed attempt.    |
| `kind`        | [codersdk.ChatErrorKind](#codersdkchaterrorkind) | false    |              | Kind classifies the retry reason for consistent client rendering. |
| `provider`    | string                                           | false    |              | Provider identifies the upstream model provider when known.       |
| `retrying_at` | string                                           | false    |              | Retrying at is the timestamp when the retry will be attempted.    |
| `status_code` | integer                                          | false    |              | Status code is the best-effort upstream HTTP status code.         |

## codersdk.ChatStreamStatus

```json
{
  "status": "waiting"
}
```

### Properties

| Name     | Type                                       | Required | Restrictions | Description |
|----------|--------------------------------------------|----------|--------------|-------------|
| `status` | [codersdk.ChatStatus](#codersdkchatstatus) | false    |              |             |

## codersdk.ChatStreamToolCall

```json
{
  "args": "string",
  "tool_call_id": "string",
  "tool_name": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `args`         | string | false    |              |             |
| `tool_call_id` | string | false    |              |             |
| `tool_name`    | string | false    |              |             |

## codersdk.ChatSystemPromptResponse

```json
{
  "default_system_prompt": "string",
  "include_default_system_prompt": true,
  "system_prompt": "string"
}
```

### Properties

| Name                            | Type    | Required | Restrictions | Description |
|---------------------------------|---------|----------|--------------|-------------|
| `default_system_prompt`         | string  | false    |              |             |
| `include_default_system_prompt` | boolean | false    |              |             |
| `system_prompt`                 | string  | false    |              |             |

## codersdk.ChatUnsupportedProvider

```json
{
  "display_name": "string",
  "provider": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description                                    |
|----------------|--------|----------|--------------|------------------------------------------------|
| `display_name` | string | false    |              |                                                |
| `provider`     | string | false    |              | Provider is the provider type, e.g. "copilot". |

## codersdk.ChatUser

```json
{
  "avatar_url": "http://example.com",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "role": "read",
  "username": "string"
}
```

### Properties

| Name         | Type                                   | Required | Restrictions | Description |
|--------------|----------------------------------------|----------|--------------|-------------|
| `avatar_url` | string                                 | false    |              |             |
| `id`         | string                                 | true     |              |             |
| `name`       | string                                 | false    |              |             |
| `role`       | [codersdk.ChatRole](#codersdkchatrole) | false    |              |             |
| `username`   | string                                 | true     |              |             |

#### Enumerated Values

| Property | Value(s) |
|----------|----------|
| `role`   | `read`   |

## codersdk.ChatWatchEvent

```json
{
  "chat": {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "archived": true,
    "build_id": "bfb1f3fa-bf7b-43a5-9e0b-26cc050e44cb",
    "children": [
      {}
    ],
    "client_type": "ui",
    "context": {
      "dirty": true,
      "dirty_since": "2019-08-24T14:15:22Z",
      "error": "string",
      "resources": [
        {
          "error": "string",
          "kind": "instruction_file",
          "size_bytes": 0,
          "skill_description": "string",
          "skill_name": "string",
          "source": "string",
          "status": "ok",
          "tools": [
            {
              "description": "string",
              "name": "string"
            }
          ]
        }
      ]
    },
    "created_at": "2019-08-24T14:15:22Z",
    "diff_status": {
      "additions": 0,
      "approved": true,
      "author_avatar_url": "string",
      "author_login": "string",
      "base_branch": "string",
      "changed_files": 0,
      "changes_requested": true,
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "commits": 0,
      "deletions": 0,
      "head_branch": "string",
      "pr_number": 0,
      "pull_request_draft": true,
      "pull_request_state": "string",
      "pull_request_title": "string",
      "refreshed_at": "2019-08-24T14:15:22Z",
      "reviewer_count": 0,
      "stale_at": "2019-08-24T14:15:22Z",
      "url": "string"
    },
    "files": [
      {
        "created_at": "2019-08-24T14:15:22Z",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "mime_type": "string",
        "name": "string",
        "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
        "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
        "size_bytes": 0
      }
    ],
    "has_unread": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "inline_mcp_servers": [
      {
        "allow_in_subagents": true,
        "created_at": "2019-08-24T14:15:22Z",
        "forward_coder_headers": true,
        "has_custom_headers": true,
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "slug": "string",
        "tool_allow_list": [
          "string"
        ],
        "tool_deny_list": [
          "string"
        ],
        "updated_at": "2019-08-24T14:15:22Z",
        "url": "string"
      }
    ],
    "labels": {
      "property1": "string",
      "property2": "string"
    },
    "last_error": {
      "detail": "string",
      "kind": "generic",
      "message": "string",
      "provider": "string",
      "retryable": true,
      "status_code": 0
    },
    "last_model_config_id": "30ebb95f-c255-4759-9429-89aa4ec1554c",
    "last_reasoning_effort": "string",
    "last_turn_summary": "string",
    "mcp_server_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
    "owner_name": "string",
    "owner_username": "string",
    "parent_chat_id": "c3609ee6-3b11-4a93-b9ae-e4fabcc99359",
    "pin_order": 0,
    "plan_mode": "plan",
    "queued_for_capacity": true,
    "root_chat_id": "2898031c-fdce-4e3e-8c53-4481dd42fcd7",
    "shared": true,
    "status": "waiting",
    "summary": "string",
    "title": "string",
    "updated_at": "2019-08-24T14:15:22Z",
    "warnings": [
      "string"
    ],
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  },
  "kind": "status_change",
  "tool_calls": [
    {
      "args": "string",
      "tool_call_id": "string",
      "tool_name": "string"
    }
  ]
}
```

### Properties

| Name         | Type                                                                | Required | Restrictions | Description |
|--------------|---------------------------------------------------------------------|----------|--------------|-------------|
| `chat`       | [codersdk.Chat](#codersdkchat)                                      | false    |              |             |
| `kind`       | [codersdk.ChatWatchEventKind](#codersdkchatwatcheventkind)          | false    |              |             |
| `tool_calls` | array of [codersdk.ChatStreamToolCall](#codersdkchatstreamtoolcall) | false    |              |             |

## codersdk.ChatWatchEventKind

```json
"status_change"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                 |
|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| `action_required`, `chat_summary_change`, `context_dirty`, `created`, `deleted`, `diff_status_change`, `status_change`, `summary_change`, `title_change` |

## codersdk.ChatWorkspaceTTLResponse

```json
{
  "workspace_ttl_ms": 0
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description                                                                                                              |
|--------------------|---------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------|
| `workspace_ttl_ms` | integer | false    |              | Workspace ttl ms is the workspace TTL in milliseconds. Zero means disabled; the template's own autostop setting applies. |

## codersdk.ClusterConfig

```json
{
  "host": "string"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description |
|--------|--------|----------|--------------|-------------|
| `host` | string | false    |              |             |

## codersdk.ConnectionLatency

```json
{
  "p50": 31.312,
  "p95": 119.832
}
```

### Properties

| Name  | Type   | Required | Restrictions | Description |
|-------|--------|----------|--------------|-------------|
| `p50` | number | false    |              |             |
| `p95` | number | false    |              |             |

## codersdk.ConnectionLog

```json
{
  "agent_name": "string",
  "connect_time": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "ip": "string",
  "organization": {
    "display_name": "string",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string"
  },
  "ssh_info": {
    "connection_id": "d3547de1-d1f2-4344-b4c2-17169b7526f9",
    "disconnect_reason": "string",
    "disconnect_time": "2019-08-24T14:15:22Z",
    "exit_code": 0
  },
  "type": "ssh",
  "web_info": {
    "slug_or_port": "string",
    "status_code": 0,
    "user": {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "has_ai_seat": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "organization_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "roles": [
        {
          "display_name": "string",
          "name": "string",
          "organization_id": "string"
        }
      ],
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    },
    "user_agent": "string"
  },
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
  "workspace_name": "string",
  "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
  "workspace_owner_username": "string"
}
```

### Properties

| Name                       | Type                                                           | Required | Restrictions | Description                                                                                                                                              |
|----------------------------|----------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_name`               | string                                                         | false    |              |                                                                                                                                                          |
| `connect_time`             | string                                                         | false    |              |                                                                                                                                                          |
| `id`                       | string                                                         | false    |              |                                                                                                                                                          |
| `ip`                       | string                                                         | false    |              |                                                                                                                                                          |
| `organization`             | [codersdk.MinimalOrganization](#codersdkminimalorganization)   | false    |              |                                                                                                                                                          |
| `ssh_info`                 | [codersdk.ConnectionLogSSHInfo](#codersdkconnectionlogsshinfo) | false    |              | Ssh info is only set when `type` is one of: - `ConnectionTypeSSH` - `ConnectionTypeReconnectingPTY` - `ConnectionTypeVSCode` - `ConnectionTypeJetBrains` |
| `type`                     | [codersdk.ConnectionType](#codersdkconnectiontype)             | false    |              |                                                                                                                                                          |
| `web_info`                 | [codersdk.ConnectionLogWebInfo](#codersdkconnectionlogwebinfo) | false    |              | Web info is only set when `type` is one of: - `ConnectionTypePortForwarding` - `ConnectionTypeWorkspaceApp` - `ConnectionTypeTunnel`                     |
| `workspace_id`             | string                                                         | false    |              |                                                                                                                                                          |
| `workspace_name`           | string                                                         | false    |              |                                                                                                                                                          |
| `workspace_owner_id`       | string                                                         | false    |              |                                                                                                                                                          |
| `workspace_owner_username` | string                                                         | false    |              |                                                                                                                                                          |

## codersdk.ConnectionLogResponse

```json
{
  "connection_logs": [
    {
      "agent_name": "string",
      "connect_time": "2019-08-24T14:15:22Z",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "ip": "string",
      "organization": {
        "display_name": "string",
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string"
      },
      "ssh_info": {
        "connection_id": "d3547de1-d1f2-4344-b4c2-17169b7526f9",
        "disconnect_reason": "string",
        "disconnect_time": "2019-08-24T14:15:22Z",
        "exit_code": 0
      },
      "type": "ssh",
      "web_info": {
        "slug_or_port": "string",
        "status_code": 0,
        "user": {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "has_ai_seat": true,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "organization_ids": [
            "497f6eca-6276-4993-bfeb-53cbbbba6f08"
          ],
          "roles": [
            {
              "display_name": "string",
              "name": "string",
              "organization_id": "string"
            }
          ],
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        },
        "user_agent": "string"
      },
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string",
      "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
      "workspace_owner_username": "string"
    }
  ],
  "count": 0,
  "count_cap": 0
}
```

### Properties

| Name              | Type                                                      | Required | Restrictions | Description |
|-------------------|-----------------------------------------------------------|----------|--------------|-------------|
| `connection_logs` | array of [codersdk.ConnectionLog](#codersdkconnectionlog) | false    |              |             |
| `count`           | integer                                                   | false    |              |             |
| `count_cap`       | integer                                                   | false    |              |             |

## codersdk.ConnectionLogSSHInfo

```json
{
  "connection_id": "d3547de1-d1f2-4344-b4c2-17169b7526f9",
  "disconnect_reason": "string",
  "disconnect_time": "2019-08-24T14:15:22Z",
  "exit_code": 0
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description                                                                                                                           |
|---------------------|---------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `connection_id`     | string  | false    |              |                                                                                                                                       |
| `disconnect_reason` | string  | false    |              | Disconnect reason is omitted if a disconnect event with the same connection ID has not yet been seen.                                 |
| `disconnect_time`   | string  | false    |              | Disconnect time is omitted if a disconnect event with the same connection ID has not yet been seen.                                   |
| `exit_code`         | integer | false    |              | Exit code is the exit code of the SSH session. It is omitted if a disconnect event with the same connection ID has not yet been seen. |

## codersdk.ConnectionLogWebInfo

```json
{
  "slug_or_port": "string",
  "status_code": 0,
  "user": {
    "avatar_url": "http://example.com",
    "created_at": "2019-08-24T14:15:22Z",
    "email": "user@example.com",
    "has_ai_seat": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "is_service_account": true,
    "last_seen_at": "2019-08-24T14:15:22Z",
    "login_type": "",
    "name": "string",
    "organization_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "roles": [
      {
        "display_name": "string",
        "name": "string",
        "organization_id": "string"
      }
    ],
    "status": "active",
    "theme_preference": "string",
    "updated_at": "2019-08-24T14:15:22Z",
    "username": "string"
  },
  "user_agent": "string"
}
```

### Properties

| Name           | Type                           | Required | Restrictions | Description                                                          |
|----------------|--------------------------------|----------|--------------|----------------------------------------------------------------------|
| `slug_or_port` | string                         | false    |              |                                                                      |
| `status_code`  | integer                        | false    |              | Status code is the HTTP status code or tunnel authorization outcome. |
| `user`         | [codersdk.User](#codersdkuser) | false    |              | User is omitted if the connection event was unauthenticated.         |
| `user_agent`   | string                         | false    |              |                                                                      |

## codersdk.ConnectionType

```json
"ssh"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                       |
|------------------------------------------------------------------------------------------------|
| `jetbrains`, `port_forwarding`, `reconnecting_pty`, `ssh`, `tunnel`, `vscode`, `workspace_app` |

## codersdk.ConvertLoginRequest

```json
{
  "password": "string",
  "to_type": ""
}
```

### Properties

| Name       | Type                                     | Required | Restrictions | Description                              |
|------------|------------------------------------------|----------|--------------|------------------------------------------|
| `password` | string                                   | true     |              |                                          |
| `to_type`  | [codersdk.LoginType](#codersdklogintype) | true     |              | To type is the login type to convert to. |

## codersdk.CreateAIGatewayKeyRequest

```json
{
  "name": "string"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description |
|--------|--------|----------|--------------|-------------|
| `name` | string | true     |              |             |

## codersdk.CreateAIGatewayKeyResponse

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "key": "string",
  "key_prefix": "string",
  "name": "string"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description |
|--------------|--------|----------|--------------|-------------|
| `created_at` | string | false    |              |             |
| `id`         | string | false    |              |             |
| `key`        | string | false    |              |             |
| `key_prefix` | string | false    |              |             |
| `name`       | string | false    |              |             |

## codersdk.CreateAIProviderRequest

```json
{
  "api_keys": [
    "string"
  ],
  "base_url": "string",
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "name": "string",
  "settings": {},
  "type": "openai"
}
```

### Properties

| Name           | Type                                                       | Required | Restrictions | Description |
|----------------|------------------------------------------------------------|----------|--------------|-------------|
| `api_keys`     | array of string                                            | false    |              |             |
| `base_url`     | string                                                     | false    |              |             |
| `display_name` | string                                                     | false    |              |             |
| `enabled`      | boolean                                                    | false    |              |             |
| `icon`         | string                                                     | false    |              |             |
| `name`         | string                                                     | false    |              |             |
| `settings`     | [codersdk.AIProviderSettings](#codersdkaiprovidersettings) | false    |              |             |
| `type`         | [codersdk.AIProviderType](#codersdkaiprovidertype)         | false    |              |             |

## codersdk.CreateChatMessageRequest

```json
{
  "busy_behavior": "queue",
  "content": [
    {
      "content": "string",
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "start_line": 0,
      "text": "string",
      "type": "text",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    }
  ],
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "forward_coder_headers": true,
      "headers": {
        "property1": "string",
        "property2": "string"
      },
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "url": "string"
    }
  ],
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
  "plan_mode": "plan",
  "reasoning_effort": "string"
}
```

### Properties

| Name                 | Type                                                                        | Required | Restrictions | Description                                                                                                  |
|----------------------|-----------------------------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------|
| `busy_behavior`      | [codersdk.ChatBusyBehavior](#codersdkchatbusybehavior)                      | false    |              |                                                                                                              |
| `content`            | array of [codersdk.ChatInputPart](#codersdkchatinputpart)                   | false    |              |                                                                                                              |
| `inline_mcp_servers` | array of [codersdk.InlineMCPServerRequest](#codersdkinlinemcpserverrequest) | false    |              | Inline mcp servers replaces the inline MCP servers. nil: no change, empty: remove all.                       |
| `mcp_server_ids`     | array of string                                                             | false    |              |                                                                                                              |
| `model_config_id`    | string                                                                      | false    |              |                                                                                                              |
| `plan_mode`          | [codersdk.ChatPlanMode](#codersdkchatplanmode)                              | false    |              | Plan mode switches the chat's persistent plan mode. nil: no change, ptr to "plan": enable, ptr to "": clear. |
| `reasoning_effort`   | string                                                                      | false    |              |                                                                                                              |

#### Enumerated Values

| Property        | Value(s)             |
|-----------------|----------------------|
| `busy_behavior` | `interrupt`, `queue` |

## codersdk.CreateChatMessageResponse

```json
{
  "message": {
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "content": [
      {
        "args": [
          0
        ],
        "args_delta": "string",
        "completed_at": "2019-08-24T14:15:22Z",
        "content": "string",
        "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
        "context_file_content": "string",
        "context_file_directory": "string",
        "context_file_os": "string",
        "context_file_path": "string",
        "context_file_skill_meta_file": "string",
        "context_file_truncated": true,
        "created_at": "2019-08-24T14:15:22Z",
        "data": [
          0
        ],
        "end_line": 0,
        "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
        "file_name": "string",
        "hook_rewritten": true,
        "is_error": true,
        "is_media": true,
        "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
        "media_type": "string",
        "name": "string",
        "parsed_commands": [
          [
            "string"
          ]
        ],
        "provider_executed": true,
        "provider_metadata": [
          0
        ],
        "reasoning_delta": "string",
        "result": [
          0
        ],
        "result_delta": "string",
        "result_reset": true,
        "skill_description": "string",
        "skill_dir": "string",
        "skill_name": "string",
        "source_id": "string",
        "start_line": 0,
        "text": "string",
        "title": "string",
        "tool_call_id": "string",
        "tool_name": "string",
        "type": "text",
        "url": "string",
        "workspace_file_media_type": "string",
        "workspace_file_name": "string",
        "workspace_file_path": "string",
        "workspace_file_size": 0,
        "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
    "id": 0,
    "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
    "queued_message_id": 0,
    "role": "system",
    "usage": {
      "cache_creation_tokens": 0,
      "cache_read_tokens": 0,
      "context_limit": 0,
      "input_tokens": 0,
      "output_tokens": 0,
      "reasoning_tokens": 0,
      "total_tokens": 0
    }
  },
  "messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
      "queued_message_id": 0,
      "role": "system",
      "usage": {
        "cache_creation_tokens": 0,
        "cache_read_tokens": 0,
        "context_limit": 0,
        "input_tokens": 0,
        "output_tokens": 0,
        "reasoning_tokens": 0,
        "total_tokens": 0
      }
    }
  ],
  "queued": true,
  "queued_message": {
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "content": [
      {
        "args": [
          0
        ],
        "args_delta": "string",
        "completed_at": "2019-08-24T14:15:22Z",
        "content": "string",
        "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
        "context_file_content": "string",
        "context_file_directory": "string",
        "context_file_os": "string",
        "context_file_path": "string",
        "context_file_skill_meta_file": "string",
        "context_file_truncated": true,
        "created_at": "2019-08-24T14:15:22Z",
        "data": [
          0
        ],
        "end_line": 0,
        "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
        "file_name": "string",
        "hook_rewritten": true,
        "is_error": true,
        "is_media": true,
        "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
        "media_type": "string",
        "name": "string",
        "parsed_commands": [
          [
            "string"
          ]
        ],
        "provider_executed": true,
        "provider_metadata": [
          0
        ],
        "reasoning_delta": "string",
        "result": [
          0
        ],
        "result_delta": "string",
        "result_reset": true,
        "skill_description": "string",
        "skill_dir": "string",
        "skill_name": "string",
        "source_id": "string",
        "start_line": 0,
        "text": "string",
        "title": "string",
        "tool_call_id": "string",
        "tool_name": "string",
        "type": "text",
        "url": "string",
        "workspace_file_media_type": "string",
        "workspace_file_name": "string",
        "workspace_file_path": "string",
        "workspace_file_size": 0,
        "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "id": 0,
    "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205"
  },
  "warnings": [
    "string"
  ]
}
```

### Properties

| Name             | Type                                                     | Required | Restrictions | Description                                                                                                                                                                                        |
|------------------|----------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `message`        | [codersdk.ChatMessage](#codersdkchatmessage)             | false    |              |                                                                                                                                                                                                    |
| `messages`       | array of [codersdk.ChatMessage](#codersdkchatmessage)    | false    |              | Messages contains all user-visible messages inserted by the send, in insertion order. A queued send on an errored chat may promote the previous queue head, so clients must upsert the full batch. |
| `queued`         | boolean                                                  | false    |              |                                                                                                                                                                                                    |
| `queued_message` | [codersdk.ChatQueuedMessage](#codersdkchatqueuedmessage) | false    |              |                                                                                                                                                                                                    |
| `warnings`       | array of string                                          | false    |              |                                                                                                                                                                                                    |

## codersdk.CreateChatModelRequest

```json
{
  "ai_provider_id": "5a3b8ff9-20e7-4c37-ba1a-5b433e355819",
  "compression_threshold": 0,
  "context_limit": 0,
  "display_name": "string",
  "enabled": true,
  "is_default": true,
  "model": "string",
  "model_config": {
    "frequency_penalty": 0,
    "max_output_tokens": 0,
    "openai_config": {
      "reasoning_model": true,
      "use_responses_api": true
    },
    "presence_penalty": 0,
    "provider_options": {
      "anthropic": {
        "allowed_domains": [
          "string"
        ],
        "blocked_domains": [
          "string"
        ],
        "context_1m_enabled": true,
        "disable_parallel_tool_use": true,
        "send_reasoning": true,
        "thinking": {
          "budget_tokens": 0
        },
        "thinking_display": "string",
        "web_search_enabled": true
      },
      "google": {
        "cached_content": "string",
        "safety_settings": [
          {
            "category": "string",
            "threshold": "string"
          }
        ],
        "thinking_config": {
          "include_thoughts": true,
          "thinking_budget": 0,
          "thinking_level": "string"
        },
        "threshold": "string",
        "web_search_enabled": true
      },
      "openai": {
        "allowed_domains": [
          "string"
        ],
        "include": [
          "string"
        ],
        "instructions": "string",
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "max_completion_tokens": 0,
        "max_tool_calls": 0,
        "metadata": {
          "property1": null,
          "property2": null
        },
        "parallel_tool_calls": true,
        "prediction": {
          "property1": null,
          "property2": null
        },
        "prompt_cache_key": "string",
        "reasoning_mode": "string",
        "reasoning_summary": "string",
        "safety_identifier": "string",
        "search_context_size": "string",
        "service_tier": "string",
        "store": true,
        "strict_json_schema": true,
        "structured_outputs": true,
        "text_verbosity": "string",
        "top_log_probs": 0,
        "user": "string",
        "web_search_enabled": true
      },
      "openaicompat": {
        "user": "string"
      },
      "openrouter": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "include_usage": true,
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "parallel_tool_calls": true,
        "provider": {
          "allow_fallbacks": true,
          "data_collection": "string",
          "ignore": [
            "string"
          ],
          "only": [
            "string"
          ],
          "order": [
            "string"
          ],
          "quantizations": [
            "string"
          ],
          "require_parameters": true,
          "sort": "string"
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "user": "string"
      },
      "vercel": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "logprobs": true,
        "parallel_tool_calls": true,
        "providerOptions": {
          "models": [
            "string"
          ],
          "order": [
            "string"
          ]
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "top_logprobs": 0,
        "user": "string"
      }
    },
    "reasoning_effort": {
      "default": "string",
      "max": "string"
    },
    "temperature": 0,
    "top_k": 0,
    "top_p": 0
  }
}
```

### Properties

| Name                    | Type                                                         | Required | Restrictions | Description |
|-------------------------|--------------------------------------------------------------|----------|--------------|-------------|
| `ai_provider_id`        | string                                                       | false    |              |             |
| `compression_threshold` | integer                                                      | false    |              |             |
| `context_limit`         | integer                                                      | false    |              |             |
| `display_name`          | string                                                       | false    |              |             |
| `enabled`               | boolean                                                      | false    |              |             |
| `is_default`            | boolean                                                      | false    |              |             |
| `model`                 | string                                                       | false    |              |             |
| `model_config`          | [codersdk.ChatModelCallConfig](#codersdkchatmodelcallconfig) | false    |              |             |

## codersdk.CreateChatRequest

```json
{
  "client_type": "ui",
  "content": [
    {
      "content": "string",
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "start_line": 0,
      "text": "string",
      "type": "text",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    }
  ],
  "inline_mcp_servers": [
    {
      "allow_in_subagents": true,
      "forward_coder_headers": true,
      "headers": {
        "property1": "string",
        "property2": "string"
      },
      "slug": "string",
      "tool_allow_list": [
        "string"
      ],
      "tool_deny_list": [
        "string"
      ],
      "url": "string"
    }
  ],
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "plan_mode": "plan",
  "reasoning_effort": "string",
  "system_prompt": "string",
  "unsafe_dynamic_tools": [
    {
      "description": "string",
      "input_schema": [
        0
      ],
      "name": "string"
    }
  ],
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Properties

| Name                   | Type                                                                        | Required | Restrictions | Description                                                                                                                                                                                           |
|------------------------|-----------------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `client_type`          | [codersdk.ChatClientType](#codersdkchatclienttype)                          | false    |              |                                                                                                                                                                                                       |
| `content`              | array of [codersdk.ChatInputPart](#codersdkchatinputpart)                   | false    |              | Content is the initial user message. It is optional: when empty, the chat is created idle with no initial user message and generation starts with the first message POSTed to /chats/{chat}/messages. |
| `inline_mcp_servers`   | array of [codersdk.InlineMCPServerRequest](#codersdkinlinemcpserverrequest) | false    |              | Inline mcp servers declares MCP servers by value on this chat, next to the org-configured servers selected by MCPServerIDs. Experimental.                                                             |
| `labels`               | object                                                                      | false    |              |                                                                                                                                                                                                       |
| » `[any property]`     | string                                                                      | false    |              |                                                                                                                                                                                                       |
| `mcp_server_ids`       | array of string                                                             | false    |              |                                                                                                                                                                                                       |
| `model_config_id`      | string                                                                      | false    |              |                                                                                                                                                                                                       |
| `organization_id`      | string                                                                      | false    |              |                                                                                                                                                                                                       |
| `owner_id`             | string                                                                      | false    |              | Owner ID makes another user the chat owner. It defaults to the caller. The chat runs with the owner's credentials, so setting it requires site-wide authority over that user.                         |
| `plan_mode`            | [codersdk.ChatPlanMode](#codersdkchatplanmode)                              | false    |              |                                                                                                                                                                                                       |
| `reasoning_effort`     | string                                                                      | false    |              |                                                                                                                                                                                                       |
| `system_prompt`        | string                                                                      | false    |              |                                                                                                                                                                                                       |
| `unsafe_dynamic_tools` | array of [codersdk.DynamicTool](#codersdkdynamictool)                       | false    |              | Unsafe dynamic tools declares client-executed tools that the LLM can invoke. This API is highly experimental and highly subject to change.                                                            |
| `workspace_id`         | string                                                                      | false    |              |                                                                                                                                                                                                       |

## codersdk.CreateFirstUserOnboardingInfo

```json
{
  "newsletter_marketing": true,
  "newsletter_releases": true
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description |
|------------------------|---------|----------|--------------|-------------|
| `newsletter_marketing` | boolean | false    |              |             |
| `newsletter_releases`  | boolean | false    |              |             |

## codersdk.CreateFirstUserRequest

```json
{
  "email": "string",
  "name": "string",
  "onboarding_info": {
    "newsletter_marketing": true,
    "newsletter_releases": true
  },
  "password": "string",
  "trial": true,
  "trial_info": {
    "company_name": "string",
    "country": "string",
    "developers": "string",
    "first_name": "string",
    "job_title": "string",
    "last_name": "string",
    "phone_number": "string"
  },
  "username": "string"
}
```

### Properties

| Name              | Type                                                                             | Required | Restrictions | Description |
|-------------------|----------------------------------------------------------------------------------|----------|--------------|-------------|
| `email`           | string                                                                           | true     |              |             |
| `name`            | string                                                                           | false    |              |             |
| `onboarding_info` | [codersdk.CreateFirstUserOnboardingInfo](#codersdkcreatefirstuseronboardinginfo) | false    |              |             |
| `password`        | string                                                                           | true     |              |             |
| `trial`           | boolean                                                                          | false    |              |             |
| `trial_info`      | [codersdk.CreateFirstUserTrialInfo](#codersdkcreatefirstusertrialinfo)           | false    |              |             |
| `username`        | string                                                                           | true     |              |             |

## codersdk.CreateFirstUserResponse

```json
{
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name              | Type   | Required | Restrictions | Description |
|-------------------|--------|----------|--------------|-------------|
| `organization_id` | string | false    |              |             |
| `user_id`         | string | false    |              |             |

## codersdk.CreateFirstUserTrialInfo

```json
{
  "company_name": "string",
  "country": "string",
  "developers": "string",
  "first_name": "string",
  "job_title": "string",
  "last_name": "string",
  "phone_number": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `company_name` | string | false    |              |             |
| `country`      | string | false    |              |             |
| `developers`   | string | false    |              |             |
| `first_name`   | string | false    |              |             |
| `job_title`    | string | false    |              |             |
| `last_name`    | string | false    |              |             |
| `phone_number` | string | false    |              |             |

## codersdk.CreateGroupRequest

```json
{
  "avatar_url": "string",
  "display_name": "string",
  "name": "string",
  "quota_allowance": 0
}
```

### Properties

| Name              | Type    | Required | Restrictions | Description |
|-------------------|---------|----------|--------------|-------------|
| `avatar_url`      | string  | false    |              |             |
| `display_name`    | string  | false    |              |             |
| `name`            | string  | true     |              |             |
| `quota_allowance` | integer | false    |              |             |

## codersdk.CreateMCPServerConfigRequest

```json
{
  "allow_in_plan_mode": true,
  "api_key_header": "string",
  "api_key_value": "string",
  "auth_type": "none",
  "availability": "force_on",
  "custom_headers": {
    "property1": "string",
    "property2": "string"
  },
  "description": "string",
  "display_name": "string",
  "enabled": true,
  "forward_coder_headers": true,
  "icon_url": "string",
  "model_intent": true,
  "oauth2_auth_url": "string",
  "oauth2_client_id": "string",
  "oauth2_client_secret": "string",
  "oauth2_revocation_url": "string",
  "oauth2_scopes": "string",
  "oauth2_token_url": "string",
  "signing_secret": "string",
  "slug": "string",
  "tool_allow_list": [
    "string"
  ],
  "tool_deny_list": [
    "string"
  ],
  "transport": "streamable_http",
  "url": "string"
}
```

### Properties

| Name                    | Type            | Required | Restrictions | Description                                                                                                                            |
|-------------------------|-----------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------|
| `allow_in_plan_mode`    | boolean         | false    |              |                                                                                                                                        |
| `api_key_header`        | string          | false    |              |                                                                                                                                        |
| `api_key_value`         | string          | false    |              |                                                                                                                                        |
| `auth_type`             | string          | true     |              |                                                                                                                                        |
| `availability`          | string          | true     |              |                                                                                                                                        |
| `custom_headers`        | object          | false    |              |                                                                                                                                        |
| » `[any property]`      | string          | false    |              |                                                                                                                                        |
| `description`           | string          | false    |              |                                                                                                                                        |
| `display_name`          | string          | true     |              |                                                                                                                                        |
| `enabled`               | boolean         | false    |              |                                                                                                                                        |
| `forward_coder_headers` | boolean         | false    |              | Forward coder headers when true, forwards Coder identity headers on every outgoing MCP request. See MCPServerConfig.                   |
| `icon_url`              | string          | false    |              |                                                                                                                                        |
| `model_intent`          | boolean         | false    |              |                                                                                                                                        |
| `oauth2_auth_url`       | string          | false    |              |                                                                                                                                        |
| `oauth2_client_id`      | string          | false    |              |                                                                                                                                        |
| `oauth2_client_secret`  | string          | false    |              |                                                                                                                                        |
| `oauth2_revocation_url` | string          | false    |              | Oauth2 revocation URL is the provider's RFC 7009 revocation endpoint; auto-populated by OAuth2 discovery when omitted.                 |
| `oauth2_scopes`         | string          | false    |              |                                                                                                                                        |
| `oauth2_token_url`      | string          | false    |              |                                                                                                                                        |
| `signing_secret`        | string          | false    |              | Signing secret signs forwarded identity headers and request bodies. Configure the same secret on the MCP server. It is never returned. |
| `slug`                  | string          | true     |              |                                                                                                                                        |
| `tool_allow_list`       | array of string | false    |              |                                                                                                                                        |
| `tool_deny_list`        | array of string | false    |              |                                                                                                                                        |
| `transport`             | string          | true     |              |                                                                                                                                        |
| `url`                   | string          | true     |              |                                                                                                                                        |

#### Enumerated Values

| Property       | Value(s)                                                   |
|----------------|------------------------------------------------------------|
| `auth_type`    | `api_key`, `custom_headers`, `none`, `oauth2`, `user_oidc` |
| `availability` | `default_off`, `default_on`, `force_on`                    |
| `transport`    | `sse`, `streamable_http`                                   |

## codersdk.CreateOrganizationRequest

```json
{
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "name": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description                                                            |
|----------------|--------|----------|--------------|------------------------------------------------------------------------|
| `description`  | string | false    |              |                                                                        |
| `display_name` | string | false    |              | Display name will default to the same value as `Name` if not provided. |
| `icon`         | string | false    |              |                                                                        |
| `name`         | string | true     |              |                                                                        |

## codersdk.CreateProvisionerKeyResponse

```json
{
  "key": "string"
}
```

### Properties

| Name  | Type   | Required | Restrictions | Description |
|-------|--------|----------|--------------|-------------|
| `key` | string | false    |              |             |

## codersdk.CreateTemplateRequest

```json
{
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "cors_behavior": "simple",
  "default_ttl_ms": 0,
  "delete_ttl_ms": 0,
  "description": "string",
  "disable_everyone_group_access": true,
  "display_name": "string",
  "dormant_ttl_ms": 0,
  "failure_ttl_ms": 0,
  "icon": "string",
  "max_port_share_level": "owner",
  "name": "string",
  "require_active_version": true,
  "template_use_classic_parameter_flow": true,
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "time_til_autostop_notify_ms": 0
}
```

### Properties

| Name                                  | Type                                                                           | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                         |
|---------------------------------------|--------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `activity_bump_ms`                    | integer                                                                        | false    |              | Activity bump ms allows optionally specifying the activity bump duration for all workspaces created from this template. Defaults to 1h but can be set to 0 to disable activity bumping.                                                                                                                             |
| `agents_allowed`                      | boolean                                                                        | false    |              | Agents allowed controls whether Coder Agents can create workspaces using this template. Defaults to true.                                                                                                                                                                                                           |
| `allow_user_autostart`                | boolean                                                                        | false    |              | Allow user autostart allows users to set a schedule for autostarting their workspace. By default this is true. This can only be disabled when using an enterprise license.                                                                                                                                          |
| `allow_user_autostop`                 | boolean                                                                        | false    |              | Allow user autostop allows users to set a custom workspace TTL to use in place of the template's DefaultTTL field. By default this is true. If false, the DefaultTTL will always be used. This can only be disabled when using an enterprise license.                                                               |
| `allow_user_cancel_workspace_jobs`    | boolean                                                                        | false    |              | Allow users to cancel in-progress workspace jobs. *bool as the default value is "true".                                                                                                                                                                                                                             |
| `allow_workspace_renames`             | boolean                                                                        | false    |              | Allow workspace renames permits users to rename workspaces built from this template. Renaming can be destructive for templates whose Terraform references the workspace name, so this defaults to false.                                                                                                            |
| `autostart_requirement`               | [codersdk.TemplateAutostartRequirement](#codersdktemplateautostartrequirement) | false    |              | Autostart requirement allows optionally specifying the autostart allowed days for workspaces created from this template. This is an enterprise feature.                                                                                                                                                             |
| `autostop_requirement`                | [codersdk.TemplateAutostopRequirement](#codersdktemplateautostoprequirement)   | false    |              | Autostop requirement allows optionally specifying the autostop requirement for workspaces created from this template. This is an enterprise feature.                                                                                                                                                                |
| `cors_behavior`                       | [codersdk.CORSBehavior](#codersdkcorsbehavior)                                 | false    |              | Cors behavior allows optionally specifying the CORS behavior for all shared ports.                                                                                                                                                                                                                                  |
| `default_ttl_ms`                      | integer                                                                        | false    |              | Default ttl ms allows optionally specifying the default TTL for all workspaces created from this template.                                                                                                                                                                                                          |
| `delete_ttl_ms`                       | integer                                                                        | false    |              | Delete ttl ms allows optionally specifying the max lifetime before Coder permanently deletes dormant workspaces created from this template.                                                                                                                                                                         |
| `description`                         | string                                                                         | false    |              | Description is a description of what the template contains. It must be less than 128 bytes.                                                                                                                                                                                                                         |
| `disable_everyone_group_access`       | boolean                                                                        | false    |              | Disable everyone group access allows optionally disabling the default behavior of granting the 'everyone' group access to use the template. If this is set to true, the template will not be available to all users, and must be explicitly granted to users or groups in the permissions settings of the template. |
| `display_name`                        | string                                                                         | false    |              | Display name is the displayed name of the template.                                                                                                                                                                                                                                                                 |
| `dormant_ttl_ms`                      | integer                                                                        | false    |              | Dormant ttl ms allows optionally specifying the max lifetime before Coder locks inactive workspaces created from this template.                                                                                                                                                                                     |
| `failure_ttl_ms`                      | integer                                                                        | false    |              | Failure ttl ms allows optionally specifying the max lifetime before Coder stops all resources for failed workspaces created from this template.                                                                                                                                                                     |
| `icon`                                | string                                                                         | false    |              | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard.                                                                                                                                                                                                                    |
| `max_port_share_level`                | [codersdk.WorkspaceAgentPortShareLevel](#codersdkworkspaceagentportsharelevel) | false    |              | Max port share level allows optionally specifying the maximum port share level for workspaces created from the template.                                                                                                                                                                                            |
| `name`                                | string                                                                         | true     |              | Name is the name of the template.                                                                                                                                                                                                                                                                                   |
| `require_active_version`              | boolean                                                                        | false    |              | Require active version mandates that workspaces are built with the active template version.                                                                                                                                                                                                                         |
| `template_use_classic_parameter_flow` | boolean                                                                        | false    |              | Template use classic parameter flow allows optionally specifying whether the template should use the classic parameter flow. The default if unset is true, and is why `*bool` is used here. When dynamic parameters becomes the default, this will default to false.                                                |
|`template_version_id`|string|true||Template version ID is an in-progress or completed job to use as an initial version of the template.
This is required on creation to enable a user-flow of validating a template works. There is no reason the data-model cannot support empty templates, but it doesn't make sense for users.|
|`time_til_autostop_notify_ms`|integer|false||Time til autostop notify ms allows optionally specifying the duration before the autostop deadline at which a reminder notification is sent for workspaces created from this template. Defaults to 0 (disabled).|

## codersdk.CreateTemplateVersionDryRunRequest

```json
{
  "rich_parameter_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "user_variable_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "workspace_name": "string"
}
```

### Properties

| Name                    | Type                                                                          | Required | Restrictions | Description |
|-------------------------|-------------------------------------------------------------------------------|----------|--------------|-------------|
| `rich_parameter_values` | array of [codersdk.WorkspaceBuildParameter](#codersdkworkspacebuildparameter) | false    |              |             |
| `user_variable_values`  | array of [codersdk.VariableValue](#codersdkvariablevalue)                     | false    |              |             |
| `workspace_name`        | string                                                                        | false    |              |             |

## codersdk.CreateTemplateVersionRequest

```json
{
  "example_id": "string",
  "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  "message": "string",
  "name": "string",
  "provisioner": "terraform",
  "storage_method": "file",
  "tags": {
    "property1": "string",
    "property2": "string"
  },
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "user_variable_values": [
    {
      "name": "string",
      "value": "string"
    }
  ]
}
```

### Properties

| Name                   | Type                                                                   | Required | Restrictions | Description                                                  |
|------------------------|------------------------------------------------------------------------|----------|--------------|--------------------------------------------------------------|
| `example_id`           | string                                                                 | false    |              |                                                              |
| `file_id`              | string                                                                 | false    |              |                                                              |
| `message`              | string                                                                 | false    |              |                                                              |
| `name`                 | string                                                                 | false    |              |                                                              |
| `provisioner`          | string                                                                 | true     |              |                                                              |
| `storage_method`       | [codersdk.ProvisionerStorageMethod](#codersdkprovisionerstoragemethod) | true     |              |                                                              |
| `tags`                 | object                                                                 | false    |              |                                                              |
| » `[any property]`     | string                                                                 | false    |              |                                                              |
| `template_id`          | string                                                                 | false    |              | Template ID optionally associates a version with a template. |
| `user_variable_values` | array of [codersdk.VariableValue](#codersdkvariablevalue)              | false    |              |                                                              |

#### Enumerated Values

| Property         | Value(s)            |
|------------------|---------------------|
| `provisioner`    | `echo`, `terraform` |
| `storage_method` | `file`              |

## codersdk.CreateTestAuditLogRequest

```json
{
  "action": "create",
  "additional_fields": [
    0
  ],
  "build_reason": "autostart",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "request_id": "266ea41d-adf5-480b-af50-15b940c2b846",
  "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
  "resource_type": "template",
  "time": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name                | Type                                           | Required | Restrictions | Description |
|---------------------|------------------------------------------------|----------|--------------|-------------|
| `action`            | [codersdk.AuditAction](#codersdkauditaction)   | false    |              |             |
| `additional_fields` | array of integer                               | false    |              |             |
| `build_reason`      | [codersdk.BuildReason](#codersdkbuildreason)   | false    |              |             |
| `organization_id`   | string                                         | false    |              |             |
| `request_id`        | string                                         | false    |              |             |
| `resource_id`       | string                                         | false    |              |             |
| `resource_type`     | [codersdk.ResourceType](#codersdkresourcetype) | false    |              |             |
| `time`              | string                                         | false    |              |             |

#### Enumerated Values

| Property        | Value(s)                                                                                                 |
|-----------------|----------------------------------------------------------------------------------------------------------|
| `action`        | `create`, `delete`, `start`, `stop`, `write`                                                             |
| `build_reason`  | `autostart`, `autostop`, `initiator`                                                                     |
| `resource_type` | `auditable_group`, `git_ssh_key`, `template`, `template_version`, `user`, `workspace`, `workspace_build` |

## codersdk.CreateTokenRequest

```json
{
  "allow_list": [
    {
      "id": "string",
      "type": "*"
    }
  ],
  "lifetime": 0,
  "scope": "all",
  "scopes": [
    "all"
  ],
  "token_name": "string"
}
```

### Properties

| Name         | Type                                                                | Required | Restrictions | Description                     |
|--------------|---------------------------------------------------------------------|----------|--------------|---------------------------------|
| `allow_list` | array of [codersdk.APIAllowListTarget](#codersdkapiallowlisttarget) | false    |              |                                 |
| `lifetime`   | integer                                                             | false    |              |                                 |
| `scope`      | [codersdk.APIKeyScope](#codersdkapikeyscope)                        | false    |              | Deprecated: use Scopes instead. |
| `scopes`     | array of [codersdk.APIKeyScope](#codersdkapikeyscope)               | false    |              |                                 |
| `token_name` | string                                                              | false    |              |                                 |

## codersdk.CreateTrialLicenseRequest

```json
{
  "attribution_id": "6f882a62-1d45-46e1-b5f4-0abfea127010",
  "company_name": "Acme Corp",
  "country": "United States",
  "developers": "string",
  "email": "jane.doe@example.com",
  "first_name": "Jane",
  "job_title": "Engineering Manager",
  "last_name": "Doe",
  "phone_number": "+14155552671",
  "source": "aibridge_session_threads"
}
```

### Properties

| Name             | Type                                                         | Required | Restrictions | Description                                                                                                                                |
|------------------|--------------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| `attribution_id` | string                                                       | false    |              | Attribution ID is the ID of the cta_click funnel event that led here, so that a signup can be joined back to the paywall that produced it. |
| `company_name`   | string                                                       | true     |              |                                                                                                                                            |
| `country`        | string                                                       | true     |              |                                                                                                                                            |
| `developers`     | string                                                       | true     |              |                                                                                                                                            |
| `email`          | string                                                       | true     |              |                                                                                                                                            |
| `first_name`     | string                                                       | true     |              |                                                                                                                                            |
| `job_title`      | string                                                       | true     |              |                                                                                                                                            |
| `last_name`      | string                                                       | true     |              |                                                                                                                                            |
| `phone_number`   | string                                                       | true     |              |                                                                                                                                            |
| `source`         | [codersdk.PremiumFunnelSource](#codersdkpremiumfunnelsource) | false    |              | Source is the premium paywall the request came from, for telemetry. It is not forwarded to the licensor. Omit it to report "direct".       |

## codersdk.CreateUserAIProviderKeyRequest

```json
{
  "api_key": "string"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description |
|-----------|--------|----------|--------------|-------------|
| `api_key` | string | false    |              |             |

## codersdk.CreateUserRequest

```json
{
  "email": "user@example.com",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "password": "string",
  "roles": [
    "string"
  ],
  "service_account": true,
  "user_status": "active",
  "username": "string"
}
```

### Properties

| Name               | Type                                       | Required | Restrictions | Description                                                                         |
|--------------------|--------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------|
| `email`            | string                                     | false    |              |                                                                                     |
| `login_type`       | [codersdk.LoginType](#codersdklogintype)   | false    |              | Login type defaults to LoginTypePassword.                                           |
| `name`             | string                                     | false    |              |                                                                                     |
| `organization_ids` | array of string                            | false    |              | Organization ids is a list of organization IDs that the user should be a member of. |
| `password`         | string                                     | false    |              |                                                                                     |
| `roles`            | array of string                            | false    |              | Roles is an optional list of site-level roles to assign at creation.                |
| `service_account`  | boolean                                    | false    |              | Service accounts are admin-managed accounts that cannot login.                      |
| `user_status`      | [codersdk.UserStatus](#codersdkuserstatus) | false    |              | User status defaults to UserStatusDormant.                                          |
| `username`         | string                                     | true     |              |                                                                                     |

## codersdk.CreateUserSecretRequest

```json
{
  "description": "string",
  "enabled": true,
  "env_name": "string",
  "file_path": "string",
  "name": "string",
  "value": "string"
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `description` | string  | false    |              |             |
| `enabled`     | boolean | false    |              |             |
| `env_name`    | string  | false    |              |             |
| `file_path`   | string  | false    |              |             |
| `name`        | string  | false    |              |             |
| `value`       | string  | false    |              |             |

## codersdk.CreateUserSkillRequest

```json
{
  "content": "string"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description                                                                                                                                                           |
|-----------|--------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `content` | string | false    |              | Content must be SKILL.md-format Markdown with YAML frontmatter. The frontmatter must include name, may include description, and must be followed by a non-empty body. |

## codersdk.CreateWorkspaceBuildOnSuccessRequest

```json
{
  "rich_parameter_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "transition": "start"
}
```

### Properties

| Name                         | Type                                                                          | Required | Restrictions | Description                                                                                                                                                                                                                                                                       |
|------------------------------|-------------------------------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `rich_parameter_values`      | array of [codersdk.WorkspaceBuildParameter](#codersdkworkspacebuildparameter) | false    |              | Rich parameter values are applied to the child build. Parameters not listed here fall back to their values from the previous build, matching normal build behavior.                                                                                                               |
| `template_version_id`        | string                                                                        | false    |              | Template version ID pins the child build to a specific template version. Pinning requires permission to update the template, since the active version may change before the child build runs. When empty, the child build uses the template's active version at the time it runs. |
| `template_version_preset_id` | string                                                                        | false    |              | Template version preset ID selects a preset for the child build. It requires TemplateVersionID to also be set.                                                                                                                                                                    |
| `transition`                 | [codersdk.WorkspaceTransition](#codersdkworkspacetransition)                  | true     |              | Transition must be "start". The parent build's transition must be "stop".                                                                                                                                                                                                         |

#### Enumerated Values

| Property     | Value(s) |
|--------------|----------|
| `transition` | `start`  |

## codersdk.CreateWorkspaceBuildReason

```json
"dashboard"
```

### Properties

#### Enumerated Values

| Value(s)                                                                          |
|-----------------------------------------------------------------------------------|
| `cli`, `dashboard`, `jetbrains_connection`, `ssh_connection`, `vscode_connection` |

## codersdk.CreateWorkspaceBuildRequest

```json
{
  "dry_run": true,
  "log_level": "debug",
  "on_success": {
    "rich_parameter_values": [
      {
        "name": "string",
        "value": "string"
      }
    ],
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start"
  },
  "orphan": true,
  "reason": "dashboard",
  "rich_parameter_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "state": [
    0
  ],
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "transition": "start"
}
```

### Properties

| Name                         | Type                                                                                           | Required | Restrictions | Description                                                                                                                                                                                                   |
|------------------------------|------------------------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `dry_run`                    | boolean                                                                                        | false    |              |                                                                                                                                                                                                               |
| `log_level`                  | [codersdk.ProvisionerLogLevel](#codersdkprovisionerloglevel)                                   | false    |              | Log level changes the default logging verbosity of a provider ("info" if empty).                                                                                                                              |
| `on_success`                 | [codersdk.CreateWorkspaceBuildOnSuccessRequest](#codersdkcreateworkspacebuildonsuccessrequest) | false    |              | On success queues a follow-up workspace build after this build succeeds. It currently supports restarting a workspace by starting it after a successful stop build.                                           |
| `orphan`                     | boolean                                                                                        | false    |              | Orphan may be set for the Destroy transition.                                                                                                                                                                 |
| `reason`                     | [codersdk.CreateWorkspaceBuildReason](#codersdkcreateworkspacebuildreason)                     | false    |              | Reason sets the reason for the workspace build.                                                                                                                                                               |
| `rich_parameter_values`      | array of [codersdk.WorkspaceBuildParameter](#codersdkworkspacebuildparameter)                  | false    |              | Rich parameter values are optional. It will write params to the 'workspace' scope. This will overwrite any existing parameters with the same name. This will not delete old params not included in this list. |
| `state`                      | array of integer                                                                               | false    |              |                                                                                                                                                                                                               |
| `template_version_id`        | string                                                                                         | false    |              |                                                                                                                                                                                                               |
| `template_version_preset_id` | string                                                                                         | false    |              | Template version preset ID is the ID of the template version preset to use for the build.                                                                                                                     |
| `transition`                 | [codersdk.WorkspaceTransition](#codersdkworkspacetransition)                                   | true     |              |                                                                                                                                                                                                               |

#### Enumerated Values

| Property     | Value(s)                                                                          |
|--------------|-----------------------------------------------------------------------------------|
| `log_level`  | `debug`                                                                           |
| `reason`     | `cli`, `dashboard`, `jetbrains_connection`, `ssh_connection`, `vscode_connection` |
| `transition` | `delete`, `start`, `stop`                                                         |

## codersdk.CreateWorkspaceProxyRequest

```json
{
  "display_name": "string",
  "icon": "string",
  "name": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `display_name` | string | false    |              |             |
| `icon`         | string | false    |              |             |
| `name`         | string | true     |              |             |

## codersdk.CreateWorkspaceRequest

```json
{
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "name": "string",
  "rich_parameter_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "ttl_ms": 0
}
```

CreateWorkspaceRequest provides options for creating a new workspace. Only one of TemplateID or TemplateVersionID can be specified, not both. If TemplateID is specified, the active version of the template will be used. Workspace names: - Must start with a letter or number - Can only contain letters, numbers, and hyphens - Cannot contain spaces or special characters - Cannot be named `new` or `create` - Must be unique within your workspaces - Maximum length of 32 characters

### Properties

| Name                         | Type                                                                          | Required | Restrictions | Description                                                                                             |
|------------------------------|-------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------|
| `automatic_updates`          | [codersdk.AutomaticUpdates](#codersdkautomaticupdates)                        | false    |              |                                                                                                         |
| `autostart_schedule`         | string                                                                        | false    |              |                                                                                                         |
| `name`                       | string                                                                        | true     |              |                                                                                                         |
| `rich_parameter_values`      | array of [codersdk.WorkspaceBuildParameter](#codersdkworkspacebuildparameter) | false    |              | Rich parameter values allows for additional parameters to be provided during the initial provision.     |
| `template_id`                | string                                                                        | false    |              | Template ID specifies which template should be used for creating the workspace.                         |
| `template_version_id`        | string                                                                        | false    |              | Template version ID can be used to specify a specific version of a template for creating the workspace. |
| `template_version_preset_id` | string                                                                        | false    |              |                                                                                                         |
| `ttl_ms`                     | integer                                                                       | false    |              |                                                                                                         |

## codersdk.CryptoKey

```json
{
  "deletes_at": "2019-08-24T14:15:22Z",
  "feature": "workspace_apps_api_key",
  "secret": "string",
  "sequence": 0,
  "starts_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name         | Type                                                   | Required | Restrictions | Description |
|--------------|--------------------------------------------------------|----------|--------------|-------------|
| `deletes_at` | string                                                 | false    |              |             |
| `feature`    | [codersdk.CryptoKeyFeature](#codersdkcryptokeyfeature) | false    |              |             |
| `secret`     | string                                                 | false    |              |             |
| `sequence`   | integer                                                | false    |              |             |
| `starts_at`  | string                                                 | false    |              |             |

## codersdk.CryptoKeyFeature

```json
"workspace_apps_api_key"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                          |
|-------------------------------------------------------------------------------------------------------------------|
| `chat_files_token`, `nats_ca`, `oidc_convert`, `tailnet_resume`, `workspace_apps_api_key`, `workspace_apps_token` |

## codersdk.CustomNotificationContent

```json
{
  "message": "string",
  "title": "string"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description |
|-----------|--------|----------|--------------|-------------|
| `message` | string | false    |              |             |
| `title`   | string | false    |              |             |

## codersdk.CustomNotificationRequest

```json
{
  "content": {
    "message": "string",
    "title": "string"
  }
}
```

### Properties

| Name      | Type                                                                     | Required | Restrictions | Description |
|-----------|--------------------------------------------------------------------------|----------|--------------|-------------|
| `content` | [codersdk.CustomNotificationContent](#codersdkcustomnotificationcontent) | false    |              |             |

## codersdk.CustomRoleRequest

```json
{
  "display_name": "string",
  "name": "string",
  "organization_member_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "organization_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "site_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "user_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ]
}
```

### Properties

| Name                              | Type                                                | Required | Restrictions | Description                                                                           |
|-----------------------------------|-----------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------|
| `display_name`                    | string                                              | false    |              |                                                                                       |
| `name`                            | string                                              | false    |              |                                                                                       |
| `organization_member_permissions` | array of [codersdk.Permission](#codersdkpermission) | false    |              | Organization member permissions are specific to the organization the role belongs to. |
| `organization_permissions`        | array of [codersdk.Permission](#codersdkpermission) | false    |              | Organization permissions are specific to the organization the role belongs to.        |
| `site_permissions`                | array of [codersdk.Permission](#codersdkpermission) | false    |              |                                                                                       |
| `user_permissions`                | array of [codersdk.Permission](#codersdkpermission) | false    |              |                                                                                       |

## codersdk.DAUEntry

```json
{
  "amount": 0,
  "date": "string"
}
```

### Properties

| Name     | Type    | Required | Restrictions | Description                                                                              |
|----------|---------|----------|--------------|------------------------------------------------------------------------------------------|
| `amount` | integer | false    |              |                                                                                          |
| `date`   | string  | false    |              | Date is a string formatted as 2024-01-31. Timezone and time information is not included. |

## codersdk.DAUsResponse

```json
{
  "entries": [
    {
      "amount": 0,
      "date": "string"
    }
  ],
  "tz_hour_offset": 0
}
```

### Properties

| Name             | Type                                            | Required | Restrictions | Description |
|------------------|-------------------------------------------------|----------|--------------|-------------|
| `entries`        | array of [codersdk.DAUEntry](#codersdkdauentry) | false    |              |             |
| `tz_hour_offset` | integer                                         | false    |              |             |

## codersdk.DERP

```json
{
  "config": {
    "block_direct": true,
    "force_websockets": true,
    "path": "string",
    "url": "string"
  },
  "server": {
    "enable": true,
    "region_code": "string",
    "region_id": 0,
    "region_name": "string",
    "relay_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "stun_addresses": [
      "string"
    ]
  }
}
```

### Properties

| Name     | Type                                                   | Required | Restrictions | Description |
|----------|--------------------------------------------------------|----------|--------------|-------------|
| `config` | [codersdk.DERPConfig](#codersdkderpconfig)             | false    |              |             |
| `server` | [codersdk.DERPServerConfig](#codersdkderpserverconfig) | false    |              |             |

## codersdk.DERPConfig

```json
{
  "block_direct": true,
  "force_websockets": true,
  "path": "string",
  "url": "string"
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description |
|--------------------|---------|----------|--------------|-------------|
| `block_direct`     | boolean | false    |              |             |
| `force_websockets` | boolean | false    |              |             |
| `path`             | string  | false    |              |             |
| `url`              | string  | false    |              |             |

## codersdk.DERPRegion

```json
{
  "latency_ms": 0,
  "preferred": true
}
```

### Properties

| Name         | Type    | Required | Restrictions | Description |
|--------------|---------|----------|--------------|-------------|
| `latency_ms` | number  | false    |              |             |
| `preferred`  | boolean | false    |              |             |

## codersdk.DERPServerConfig

```json
{
  "enable": true,
  "region_code": "string",
  "region_id": 0,
  "region_name": "string",
  "relay_url": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  },
  "stun_addresses": [
    "string"
  ]
}
```

### Properties

| Name             | Type                       | Required | Restrictions | Description |
|------------------|----------------------------|----------|--------------|-------------|
| `enable`         | boolean                    | false    |              |             |
| `region_code`    | string                     | false    |              |             |
| `region_id`      | integer                    | false    |              |             |
| `region_name`    | string                     | false    |              |             |
| `relay_url`      | [serpent.URL](#serpenturl) | false    |              |             |
| `stun_addresses` | array of string            | false    |              |             |

## codersdk.DangerousConfig

```json
{
  "allow_all_cors": true,
  "allow_path_app_sharing": true,
  "allow_path_app_site_owner_access": true
}
```

### Properties

| Name                               | Type    | Required | Restrictions | Description |
|------------------------------------|---------|----------|--------------|-------------|
| `allow_all_cors`                   | boolean | false    |              |             |
| `allow_path_app_sharing`           | boolean | false    |              |             |
| `allow_path_app_site_owner_access` | boolean | false    |              |             |

## codersdk.DeleteExternalAuthByIDResponse

```json
{
  "token_revocation_error": "string",
  "token_revoked": true
}
```

### Properties

| Name                     | Type    | Required | Restrictions | Description                                                                    |
|--------------------------|---------|----------|--------------|--------------------------------------------------------------------------------|
| `token_revocation_error` | string  | false    |              |                                                                                |
| `token_revoked`          | boolean | false    |              | Token revoked set to true if token revocation was attempted and was successful |

## codersdk.DeleteWebpushSubscription

```json
{
  "endpoint": "string"
}
```

### Properties

| Name       | Type   | Required | Restrictions | Description |
|------------|--------|----------|--------------|-------------|
| `endpoint` | string | false    |              |             |

## codersdk.DeleteWorkspaceAgentPortShareRequest

```json
{
  "agent_name": "string",
  "port": 0
}
```

### Properties

| Name         | Type    | Required | Restrictions | Description |
|--------------|---------|----------|--------------|-------------|
| `agent_name` | string  | false    |              |             |
| `port`       | integer | false    |              |             |

## codersdk.DeploymentConfig

```json
{
  "config": {
    "access_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "additional_csp_policy": [
      "string"
    ],
    "address": {
      "host": "string",
      "port": "string"
    },
    "agent_fallback_troubleshooting_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "agent_stat_refresh_interval": 0,
    "ai": {
      "aibridge_proxy": {
        "allowed_private_cidrs": [
          "string"
        ],
        "api_dump_dir": "string",
        "cert_file": "string",
        "domain_allowlist": [
          "string"
        ],
        "enabled": true,
        "key_file": "string",
        "listen_addr": "string",
        "target": "string",
        "tls_cert_file": "string",
        "tls_key_file": "string",
        "upstream_proxy": "string",
        "upstream_proxy_ca": "string"
      },
      "bridge": {
        "actor_header_email": "string",
        "actor_header_id": "string",
        "actor_header_username": "string",
        "allow_byok": true,
        "api_dump_dir": "string",
        "budget_period": "string",
        "budget_policy": "string",
        "circuit_breaker_enabled": true,
        "circuit_breaker_failure_threshold": 0,
        "circuit_breaker_interval": 0,
        "circuit_breaker_max_requests": 0,
        "circuit_breaker_timeout": 0,
        "disable_content_recording": true,
        "enabled": true,
        "inject_coder_mcp_tools": true,
        "max_concurrency": 0,
        "rate_limit": 0,
        "retention": 0,
        "send_actor_headers": true,
        "structured_logging": true,
        "structured_logging_source": "string"
      },
      "chat": {
        "acquire_batch_size": 0,
        "debug_logging_enabled": true,
        "hook_allow_insecure": true,
        "hook_enabled": true,
        "hook_secret": "string",
        "hook_timeout": 0,
        "hook_url": {
          "forceQuery": true,
          "fragment": "string",
          "host": "string",
          "omitHost": true,
          "opaque": "string",
          "path": "string",
          "rawFragment": "string",
          "rawPath": "string",
          "rawQuery": "string",
          "scheme": "string",
          "user": {}
        },
        "max_attachments_per_chat": 0,
        "max_concurrent_recording_uploads": 0,
        "max_generation_retries": 0,
        "max_prompt_bytes": 0,
        "max_queued_messages_per_chat": 0,
        "max_steps_per_turn": 0,
        "stream_silence_timeout": 0
      }
    },
    "allow_workspace_renames": true,
    "autobuild_poll_interval": 0,
    "browser_only": true,
    "cache_directory": "string",
    "cli_upgrade_message": "string",
    "cluster": {
      "host": "string"
    },
    "config": "string",
    "config_ssh": {
      "deploymentName": "string",
      "sshconfigOptions": [
        "string"
      ]
    },
    "dangerous": {
      "allow_all_cors": true,
      "allow_path_app_sharing": true,
      "allow_path_app_site_owner_access": true
    },
    "derp": {
      "config": {
        "block_direct": true,
        "force_websockets": true,
        "path": "string",
        "url": "string"
      },
      "server": {
        "enable": true,
        "region_code": "string",
        "region_id": 0,
        "region_name": "string",
        "relay_url": {
          "forceQuery": true,
          "fragment": "string",
          "host": "string",
          "omitHost": true,
          "opaque": "string",
          "path": "string",
          "rawFragment": "string",
          "rawPath": "string",
          "rawQuery": "string",
          "scheme": "string",
          "user": {}
        },
        "stun_addresses": [
          "string"
        ]
      }
    },
    "disable_chat_caller_supplied_tools": true,
    "disable_chat_sharing": true,
    "disable_owner_workspace_exec": true,
    "disable_password_auth": true,
    "disable_path_apps": true,
    "disable_user_secret_file_path": true,
    "disable_workspace_agent_context_sync": true,
    "disable_workspace_sharing": true,
    "docs_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "dynamic_parameters_full_evaluation": true,
    "enable_authz_recording": true,
    "enable_terraform_debug_mode": true,
    "ephemeral_deployment": true,
    "experiments": [
      "string"
    ],
    "external_auth": {
      "value": [
        {
          "api_base_url": "string",
          "app_install_url": "string",
          "app_installations_url": "string",
          "auth_url": "string",
          "client_id": "string",
          "code_challenge_methods_supported": [
            "string"
          ],
          "device_code_url": "string",
          "device_flow": true,
          "display_icon": "string",
          "display_name": "string",
          "id": "string",
          "mcp_tool_allow_regex": "string",
          "mcp_tool_deny_regex": "string",
          "mcp_url": "string",
          "no_refresh": true,
          "redirect_url": "string",
          "regex": "string",
          "revoke_url": "string",
          "scopes": [
            "string"
          ],
          "token_url": "string",
          "type": "string",
          "validate_url": "string"
        }
      ]
    },
    "external_auth_github_default_provider_enable": true,
    "external_token_encryption_keys": [
      "string"
    ],
    "healthcheck": {
      "refresh": 0,
      "threshold_database": 0
    },
    "http_address": "string",
    "http_cookies": {
      "host_prefix": true,
      "same_site": "string",
      "secure_auth_cookie": true
    },
    "job_hang_detector_interval": 0,
    "logging": {
      "human": "string",
      "json": "string",
      "log_filter": [
        "string"
      ],
      "stackdriver": "string"
    },
    "mcp_allowed_private_cidrs": [
      "string"
    ],
    "metrics_cache_refresh_interval": 0,
    "notifications": {
      "dispatch_timeout": 0,
      "email": {
        "auth": {
          "identity": "string",
          "password": "string",
          "password_file": "string",
          "username": "string"
        },
        "force_tls": true,
        "from": "string",
        "hello": "string",
        "smarthost": "string",
        "tls": {
          "ca_file": "string",
          "cert_file": "string",
          "insecure_skip_verify": true,
          "key_file": "string",
          "server_name": "string",
          "start_tls": true
        }
      },
      "fetch_interval": 0,
      "inbox": {
        "enabled": true
      },
      "lease_count": 0,
      "lease_period": 0,
      "max_send_attempts": 0,
      "method": "string",
      "retry_interval": 0,
      "sync_buffer_size": 0,
      "sync_interval": 0,
      "webhook": {
        "endpoint": {
          "forceQuery": true,
          "fragment": "string",
          "host": "string",
          "omitHost": true,
          "opaque": "string",
          "path": "string",
          "rawFragment": "string",
          "rawPath": "string",
          "rawQuery": "string",
          "scheme": "string",
          "user": {}
        }
      }
    },
    "oauth2": {
      "github": {
        "allow_everyone": true,
        "allow_signups": true,
        "allowed_orgs": [
          "string"
        ],
        "allowed_teams": [
          "string"
        ],
        "client_id": "string",
        "client_secret": "string",
        "default_provider_enable": true,
        "device_flow": true,
        "enterprise_base_url": "string"
      },
      "provider": {
        "enable": true
      }
    },
    "oidc": {
      "allow_signups": true,
      "auth_url_params": {},
      "auto_repair_links": true,
      "client_cert_file": "string",
      "client_id": "string",
      "client_key_file": "string",
      "client_secret": "string",
      "email_domain": [
        "string"
      ],
      "email_fallback": true,
      "email_field": "string",
      "group_allow_list": [
        "string"
      ],
      "group_auto_create": true,
      "group_mapping": {},
      "group_regex_filter": {},
      "groups_field": "string",
      "icon_url": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      },
      "ignore_email_verified": true,
      "ignore_user_info": true,
      "issuer_url": "string",
      "name_field": "string",
      "organization_assign_default": true,
      "organization_field": "string",
      "organization_mapping": {},
      "redirect_allowed_hosts": [
        "string"
      ],
      "redirect_url": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      },
      "scopes": [
        "string"
      ],
      "sign_in_text": "string",
      "signups_disabled_text": "string",
      "skip_issuer_checks": true,
      "source_user_info_from_access_token": true,
      "user_role_field": "string",
      "user_role_mapping": {},
      "user_roles_default": [
        "string"
      ],
      "username_field": "string"
    },
    "pg_auth": "string",
    "pg_conn_max_idle": "string",
    "pg_conn_max_open": 0,
    "pg_connection_url": "string",
    "pprof": {
      "address": {
        "host": "string",
        "port": "string"
      },
      "enable": true
    },
    "prometheus": {
      "address": {
        "host": "string",
        "port": "string"
      },
      "aggregate_agent_stats_by": [
        "string"
      ],
      "collect_agent_stats": true,
      "collect_db_metrics": true,
      "enable": true
    },
    "provisioner": {
      "daemon_poll_interval": 0,
      "daemon_poll_jitter": 0,
      "daemon_psk": "string",
      "daemon_types": [
        "string"
      ],
      "daemons": 0,
      "disable_module_cache": true,
      "force_cancel_interval": 0
    },
    "proxy_health_status_interval": 0,
    "proxy_trusted_headers": [
      "string"
    ],
    "proxy_trusted_origins": [
      "string"
    ],
    "rate_limit": {
      "api": 0,
      "disable_all": true
    },
    "redirect_to_access_url": true,
    "retention": {
      "api_keys": 0,
      "audit_logs": 0,
      "boundary_logs": 0,
      "connection_logs": 0,
      "workspace_agent_logs": 0
    },
    "scim_api_key": "string",
    "scim_use_legacy": true,
    "session_lifetime": {
      "default_duration": 0,
      "default_token_lifetime": 0,
      "disable_expiry_refresh": true,
      "max_admin_token_lifetime": 0,
      "max_token_lifetime": 0,
      "refresh_default_duration": 0
    },
    "ssh_keygen_algorithm": "string",
    "stats_collection": {
      "usage_stats": {
        "enable": true
      }
    },
    "strict_transport_security": 0,
    "strict_transport_security_options": [
      "string"
    ],
    "support": {
      "links": {
        "value": [
          {
            "icon": "bug",
            "location": "navbar",
            "name": "string",
            "target": "string"
          }
        ]
      }
    },
    "swagger": {
      "enable": true
    },
    "telemetry": {
      "enable": true,
      "trace": true,
      "url": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      }
    },
    "template_builder": {
      "disabled": true,
      "registry_url": "string"
    },
    "terms_of_service_url": "string",
    "tls": {
      "address": {
        "host": "string",
        "port": "string"
      },
      "allow_insecure_ciphers": true,
      "cert_file": [
        "string"
      ],
      "client_auth": "string",
      "client_ca_file": "string",
      "client_cert_file": "string",
      "client_key_file": "string",
      "enable": true,
      "key_file": [
        "string"
      ],
      "min_version": "string",
      "redirect_http": true,
      "supported_ciphers": [
        "string"
      ]
    },
    "trace": {
      "capture_logs": true,
      "data_dog": true,
      "enable": true,
      "honeycomb_api_key": "string"
    },
    "update_check": true,
    "user_quiet_hours_schedule": {
      "allow_user_custom": true,
      "default_schedule": "string"
    },
    "verbose": true,
    "web_terminal_renderer": "string",
    "wgtunnel_host": "string",
    "wildcard_access_url": "string",
    "workspace_hostname_suffix": "string",
    "workspace_prebuilds": {
      "failure_hard_limit": 0,
      "reconciliation_backoff_interval": 0,
      "reconciliation_backoff_lookback": 0,
      "reconciliation_interval": 0
    },
    "write_config": true
  },
  "options": [
    {
      "annotations": {
        "property1": "string",
        "property2": "string"
      },
      "default": "string",
      "description": "string",
      "env": "string",
      "flag": "string",
      "flag_shorthand": "string",
      "group": {
        "description": "string",
        "name": "string",
        "parent": {
          "description": "string",
          "name": "string",
          "parent": {},
          "yaml": "string"
        },
        "yaml": "string"
      },
      "hidden": true,
      "name": "string",
      "required": true,
      "use_instead": [
        {}
      ],
      "value": null,
      "value_source": "",
      "yaml": "string"
    }
  ]
}
```

### Properties

| Name      | Type                                                   | Required | Restrictions | Description |
|-----------|--------------------------------------------------------|----------|--------------|-------------|
| `config`  | [codersdk.DeploymentValues](#codersdkdeploymentvalues) | false    |              |             |
| `options` | array of [serpent.Option](#serpentoption)              | false    |              |             |

## codersdk.DeploymentStats

```json
{
  "aggregated_from": "2019-08-24T14:15:22Z",
  "collected_at": "2019-08-24T14:15:22Z",
  "next_update_at": "2019-08-24T14:15:22Z",
  "session_count": {
    "apps": {
      "property1": {
        "count": 0,
        "display_name": "string",
        "family": "vscode",
        "icon": "string"
      },
      "property2": {
        "count": 0,
        "display_name": "string",
        "family": "vscode",
        "icon": "string"
      }
    },
    "jetbrains": 0,
    "reconnecting_pty": 0,
    "ssh": 0,
    "vscode": 0
  },
  "workspaces": {
    "building": 0,
    "connection_latency_ms": {
      "p50": 0,
      "p95": 0
    },
    "failed": 0,
    "pending": 0,
    "running": 0,
    "rx_bytes": 0,
    "stopped": 0,
    "tx_bytes": 0
  }
}
```

### Properties

| Name              | Type                                                                         | Required | Restrictions | Description                                                                                                                 |
|-------------------|------------------------------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------|
| `aggregated_from` | string                                                                       | false    |              | Aggregated from is the time in which stats are aggregated from. This might be back in time a specific duration or interval. |
| `collected_at`    | string                                                                       | false    |              | Collected at is the time in which stats are collected at.                                                                   |
| `next_update_at`  | string                                                                       | false    |              | Next update at is the time when the next batch of stats will be updated.                                                    |
| `session_count`   | [codersdk.SessionCountDeploymentStats](#codersdksessioncountdeploymentstats) | false    |              |                                                                                                                             |
| `workspaces`      | [codersdk.WorkspaceDeploymentStats](#codersdkworkspacedeploymentstats)       | false    |              |                                                                                                                             |

## codersdk.DeploymentValues

```json
{
  "access_url": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  },
  "additional_csp_policy": [
    "string"
  ],
  "address": {
    "host": "string",
    "port": "string"
  },
  "agent_fallback_troubleshooting_url": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  },
  "agent_stat_refresh_interval": 0,
  "ai": {
    "aibridge_proxy": {
      "allowed_private_cidrs": [
        "string"
      ],
      "api_dump_dir": "string",
      "cert_file": "string",
      "domain_allowlist": [
        "string"
      ],
      "enabled": true,
      "key_file": "string",
      "listen_addr": "string",
      "target": "string",
      "tls_cert_file": "string",
      "tls_key_file": "string",
      "upstream_proxy": "string",
      "upstream_proxy_ca": "string"
    },
    "bridge": {
      "actor_header_email": "string",
      "actor_header_id": "string",
      "actor_header_username": "string",
      "allow_byok": true,
      "api_dump_dir": "string",
      "budget_period": "string",
      "budget_policy": "string",
      "circuit_breaker_enabled": true,
      "circuit_breaker_failure_threshold": 0,
      "circuit_breaker_interval": 0,
      "circuit_breaker_max_requests": 0,
      "circuit_breaker_timeout": 0,
      "disable_content_recording": true,
      "enabled": true,
      "inject_coder_mcp_tools": true,
      "max_concurrency": 0,
      "rate_limit": 0,
      "retention": 0,
      "send_actor_headers": true,
      "structured_logging": true,
      "structured_logging_source": "string"
    },
    "chat": {
      "acquire_batch_size": 0,
      "debug_logging_enabled": true,
      "hook_allow_insecure": true,
      "hook_enabled": true,
      "hook_secret": "string",
      "hook_timeout": 0,
      "hook_url": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      },
      "max_attachments_per_chat": 0,
      "max_concurrent_recording_uploads": 0,
      "max_generation_retries": 0,
      "max_prompt_bytes": 0,
      "max_queued_messages_per_chat": 0,
      "max_steps_per_turn": 0,
      "stream_silence_timeout": 0
    }
  },
  "allow_workspace_renames": true,
  "autobuild_poll_interval": 0,
  "browser_only": true,
  "cache_directory": "string",
  "cli_upgrade_message": "string",
  "cluster": {
    "host": "string"
  },
  "config": "string",
  "config_ssh": {
    "deploymentName": "string",
    "sshconfigOptions": [
      "string"
    ]
  },
  "dangerous": {
    "allow_all_cors": true,
    "allow_path_app_sharing": true,
    "allow_path_app_site_owner_access": true
  },
  "derp": {
    "config": {
      "block_direct": true,
      "force_websockets": true,
      "path": "string",
      "url": "string"
    },
    "server": {
      "enable": true,
      "region_code": "string",
      "region_id": 0,
      "region_name": "string",
      "relay_url": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      },
      "stun_addresses": [
        "string"
      ]
    }
  },
  "disable_chat_caller_supplied_tools": true,
  "disable_chat_sharing": true,
  "disable_owner_workspace_exec": true,
  "disable_password_auth": true,
  "disable_path_apps": true,
  "disable_user_secret_file_path": true,
  "disable_workspace_agent_context_sync": true,
  "disable_workspace_sharing": true,
  "docs_url": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  },
  "dynamic_parameters_full_evaluation": true,
  "enable_authz_recording": true,
  "enable_terraform_debug_mode": true,
  "ephemeral_deployment": true,
  "experiments": [
    "string"
  ],
  "external_auth": {
    "value": [
      {
        "api_base_url": "string",
        "app_install_url": "string",
        "app_installations_url": "string",
        "auth_url": "string",
        "client_id": "string",
        "code_challenge_methods_supported": [
          "string"
        ],
        "device_code_url": "string",
        "device_flow": true,
        "display_icon": "string",
        "display_name": "string",
        "id": "string",
        "mcp_tool_allow_regex": "string",
        "mcp_tool_deny_regex": "string",
        "mcp_url": "string",
        "no_refresh": true,
        "redirect_url": "string",
        "regex": "string",
        "revoke_url": "string",
        "scopes": [
          "string"
        ],
        "token_url": "string",
        "type": "string",
        "validate_url": "string"
      }
    ]
  },
  "external_auth_github_default_provider_enable": true,
  "external_token_encryption_keys": [
    "string"
  ],
  "healthcheck": {
    "refresh": 0,
    "threshold_database": 0
  },
  "http_address": "string",
  "http_cookies": {
    "host_prefix": true,
    "same_site": "string",
    "secure_auth_cookie": true
  },
  "job_hang_detector_interval": 0,
  "logging": {
    "human": "string",
    "json": "string",
    "log_filter": [
      "string"
    ],
    "stackdriver": "string"
  },
  "mcp_allowed_private_cidrs": [
    "string"
  ],
  "metrics_cache_refresh_interval": 0,
  "notifications": {
    "dispatch_timeout": 0,
    "email": {
      "auth": {
        "identity": "string",
        "password": "string",
        "password_file": "string",
        "username": "string"
      },
      "force_tls": true,
      "from": "string",
      "hello": "string",
      "smarthost": "string",
      "tls": {
        "ca_file": "string",
        "cert_file": "string",
        "insecure_skip_verify": true,
        "key_file": "string",
        "server_name": "string",
        "start_tls": true
      }
    },
    "fetch_interval": 0,
    "inbox": {
      "enabled": true
    },
    "lease_count": 0,
    "lease_period": 0,
    "max_send_attempts": 0,
    "method": "string",
    "retry_interval": 0,
    "sync_buffer_size": 0,
    "sync_interval": 0,
    "webhook": {
      "endpoint": {
        "forceQuery": true,
        "fragment": "string",
        "host": "string",
        "omitHost": true,
        "opaque": "string",
        "path": "string",
        "rawFragment": "string",
        "rawPath": "string",
        "rawQuery": "string",
        "scheme": "string",
        "user": {}
      }
    }
  },
  "oauth2": {
    "github": {
      "allow_everyone": true,
      "allow_signups": true,
      "allowed_orgs": [
        "string"
      ],
      "allowed_teams": [
        "string"
      ],
      "client_id": "string",
      "client_secret": "string",
      "default_provider_enable": true,
      "device_flow": true,
      "enterprise_base_url": "string"
    },
    "provider": {
      "enable": true
    }
  },
  "oidc": {
    "allow_signups": true,
    "auth_url_params": {},
    "auto_repair_links": true,
    "client_cert_file": "string",
    "client_id": "string",
    "client_key_file": "string",
    "client_secret": "string",
    "email_domain": [
      "string"
    ],
    "email_fallback": true,
    "email_field": "string",
    "group_allow_list": [
      "string"
    ],
    "group_auto_create": true,
    "group_mapping": {},
    "group_regex_filter": {},
    "groups_field": "string",
    "icon_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "ignore_email_verified": true,
    "ignore_user_info": true,
    "issuer_url": "string",
    "name_field": "string",
    "organization_assign_default": true,
    "organization_field": "string",
    "organization_mapping": {},
    "redirect_allowed_hosts": [
      "string"
    ],
    "redirect_url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    },
    "scopes": [
      "string"
    ],
    "sign_in_text": "string",
    "signups_disabled_text": "string",
    "skip_issuer_checks": true,
    "source_user_info_from_access_token": true,
    "user_role_field": "string",
    "user_role_mapping": {},
    "user_roles_default": [
      "string"
    ],
    "username_field": "string"
  },
  "pg_auth": "string",
  "pg_conn_max_idle": "string",
  "pg_conn_max_open": 0,
  "pg_connection_url": "string",
  "pprof": {
    "address": {
      "host": "string",
      "port": "string"
    },
    "enable": true
  },
  "prometheus": {
    "address": {
      "host": "string",
      "port": "string"
    },
    "aggregate_agent_stats_by": [
      "string"
    ],
    "collect_agent_stats": true,
    "collect_db_metrics": true,
    "enable": true
  },
  "provisioner": {
    "daemon_poll_interval": 0,
    "daemon_poll_jitter": 0,
    "daemon_psk": "string",
    "daemon_types": [
      "string"
    ],
    "daemons": 0,
    "disable_module_cache": true,
    "force_cancel_interval": 0
  },
  "proxy_health_status_interval": 0,
  "proxy_trusted_headers": [
    "string"
  ],
  "proxy_trusted_origins": [
    "string"
  ],
  "rate_limit": {
    "api": 0,
    "disable_all": true
  },
  "redirect_to_access_url": true,
  "retention": {
    "api_keys": 0,
    "audit_logs": 0,
    "boundary_logs": 0,
    "connection_logs": 0,
    "workspace_agent_logs": 0
  },
  "scim_api_key": "string",
  "scim_use_legacy": true,
  "session_lifetime": {
    "default_duration": 0,
    "default_token_lifetime": 0,
    "disable_expiry_refresh": true,
    "max_admin_token_lifetime": 0,
    "max_token_lifetime": 0,
    "refresh_default_duration": 0
  },
  "ssh_keygen_algorithm": "string",
  "stats_collection": {
    "usage_stats": {
      "enable": true
    }
  },
  "strict_transport_security": 0,
  "strict_transport_security_options": [
    "string"
  ],
  "support": {
    "links": {
      "value": [
        {
          "icon": "bug",
          "location": "navbar",
          "name": "string",
          "target": "string"
        }
      ]
    }
  },
  "swagger": {
    "enable": true
  },
  "telemetry": {
    "enable": true,
    "trace": true,
    "url": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    }
  },
  "template_builder": {
    "disabled": true,
    "registry_url": "string"
  },
  "terms_of_service_url": "string",
  "tls": {
    "address": {
      "host": "string",
      "port": "string"
    },
    "allow_insecure_ciphers": true,
    "cert_file": [
      "string"
    ],
    "client_auth": "string",
    "client_ca_file": "string",
    "client_cert_file": "string",
    "client_key_file": "string",
    "enable": true,
    "key_file": [
      "string"
    ],
    "min_version": "string",
    "redirect_http": true,
    "supported_ciphers": [
      "string"
    ]
  },
  "trace": {
    "capture_logs": true,
    "data_dog": true,
    "enable": true,
    "honeycomb_api_key": "string"
  },
  "update_check": true,
  "user_quiet_hours_schedule": {
    "allow_user_custom": true,
    "default_schedule": "string"
  },
  "verbose": true,
  "web_terminal_renderer": "string",
  "wgtunnel_host": "string",
  "wildcard_access_url": "string",
  "workspace_hostname_suffix": "string",
  "workspace_prebuilds": {
    "failure_hard_limit": 0,
    "reconciliation_backoff_interval": 0,
    "reconciliation_backoff_lookback": 0,
    "reconciliation_interval": 0
  },
  "write_config": true
}
```

### Properties

| Name                                           | Type                                                                                                 | Required | Restrictions | Description                                                               |
|------------------------------------------------|------------------------------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------|
| `access_url`                                   | [serpent.URL](#serpenturl)                                                                           | false    |              |                                                                           |
| `additional_csp_policy`                        | array of string                                                                                      | false    |              |                                                                           |
| `address`                                      | [serpent.HostPort](#serpenthostport)                                                                 | false    |              | Deprecated: Use HTTPAddress or TLS.Address instead.                       |
| `agent_fallback_troubleshooting_url`           | [serpent.URL](#serpenturl)                                                                           | false    |              |                                                                           |
| `agent_stat_refresh_interval`                  | integer                                                                                              | false    |              |                                                                           |
| `ai`                                           | [codersdk.AIConfig](#codersdkaiconfig)                                                               | false    |              |                                                                           |
| `allow_workspace_renames`                      | boolean                                                                                              | false    |              | Deprecated: Use the per-template allow_workspace_renames setting instead. |
| `autobuild_poll_interval`                      | integer                                                                                              | false    |              |                                                                           |
| `browser_only`                                 | boolean                                                                                              | false    |              |                                                                           |
| `cache_directory`                              | string                                                                                               | false    |              |                                                                           |
| `cli_upgrade_message`                          | string                                                                                               | false    |              |                                                                           |
| `cluster`                                      | [codersdk.ClusterConfig](#codersdkclusterconfig)                                                     | false    |              |                                                                           |
| `config`                                       | string                                                                                               | false    |              |                                                                           |
| `config_ssh`                                   | [codersdk.SSHConfig](#codersdksshconfig)                                                             | false    |              |                                                                           |
| `dangerous`                                    | [codersdk.DangerousConfig](#codersdkdangerousconfig)                                                 | false    |              |                                                                           |
| `derp`                                         | [codersdk.DERP](#codersdkderp)                                                                       | false    |              |                                                                           |
| `disable_chat_caller_supplied_tools`           | boolean                                                                                              | false    |              |                                                                           |
| `disable_chat_sharing`                         | boolean                                                                                              | false    |              |                                                                           |
| `disable_owner_workspace_exec`                 | boolean                                                                                              | false    |              |                                                                           |
| `disable_password_auth`                        | boolean                                                                                              | false    |              |                                                                           |
| `disable_path_apps`                            | boolean                                                                                              | false    |              |                                                                           |
| `disable_user_secret_file_path`                | boolean                                                                                              | false    |              |                                                                           |
| `disable_workspace_agent_context_sync`         | boolean                                                                                              | false    |              |                                                                           |
| `disable_workspace_sharing`                    | boolean                                                                                              | false    |              |                                                                           |
| `docs_url`                                     | [serpent.URL](#serpenturl)                                                                           | false    |              |                                                                           |
| `dynamic_parameters_full_evaluation`           | boolean                                                                                              | false    |              |                                                                           |
| `enable_authz_recording`                       | boolean                                                                                              | false    |              |                                                                           |
| `enable_terraform_debug_mode`                  | boolean                                                                                              | false    |              |                                                                           |
| `ephemeral_deployment`                         | boolean                                                                                              | false    |              |                                                                           |
| `experiments`                                  | array of string                                                                                      | false    |              |                                                                           |
| `external_auth`                                | [serpent.Struct-array_codersdk_ExternalAuthConfig](#serpentstruct-array_codersdk_externalauthconfig) | false    |              |                                                                           |
| `external_auth_github_default_provider_enable` | boolean                                                                                              | false    |              |                                                                           |
| `external_token_encryption_keys`               | array of string                                                                                      | false    |              |                                                                           |
| `healthcheck`                                  | [codersdk.HealthcheckConfig](#codersdkhealthcheckconfig)                                             | false    |              |                                                                           |
| `http_address`                                 | string                                                                                               | false    |              | Http address is a string because it may be set to zero to disable.        |
| `http_cookies`                                 | [codersdk.HTTPCookieConfig](#codersdkhttpcookieconfig)                                               | false    |              |                                                                           |
| `job_hang_detector_interval`                   | integer                                                                                              | false    |              |                                                                           |
| `logging`                                      | [codersdk.LoggingConfig](#codersdkloggingconfig)                                                     | false    |              |                                                                           |
| `mcp_allowed_private_cidrs`                    | array of string                                                                                      | false    |              |                                                                           |
| `metrics_cache_refresh_interval`               | integer                                                                                              | false    |              |                                                                           |
| `notifications`                                | [codersdk.NotificationsConfig](#codersdknotificationsconfig)                                         | false    |              |                                                                           |
| `oauth2`                                       | [codersdk.OAuth2Config](#codersdkoauth2config)                                                       | false    |              |                                                                           |
| `oidc`                                         | [codersdk.OIDCConfig](#codersdkoidcconfig)                                                           | false    |              |                                                                           |
| `pg_auth`                                      | string                                                                                               | false    |              |                                                                           |
| `pg_conn_max_idle`                             | string                                                                                               | false    |              |                                                                           |
| `pg_conn_max_open`                             | integer                                                                                              | false    |              |                                                                           |
| `pg_connection_url`                            | string                                                                                               | false    |              |                                                                           |
| `pprof`                                        | [codersdk.PprofConfig](#codersdkpprofconfig)                                                         | false    |              |                                                                           |
| `prometheus`                                   | [codersdk.PrometheusConfig](#codersdkprometheusconfig)                                               | false    |              |                                                                           |
| `provisioner`                                  | [codersdk.ProvisionerConfig](#codersdkprovisionerconfig)                                             | false    |              |                                                                           |
| `proxy_health_status_interval`                 | integer                                                                                              | false    |              |                                                                           |
| `proxy_trusted_headers`                        | array of string                                                                                      | false    |              |                                                                           |
| `proxy_trusted_origins`                        | array of string                                                                                      | false    |              |                                                                           |
| `rate_limit`                                   | [codersdk.RateLimitConfig](#codersdkratelimitconfig)                                                 | false    |              |                                                                           |
| `redirect_to_access_url`                       | boolean                                                                                              | false    |              |                                                                           |
| `retention`                                    | [codersdk.RetentionConfig](#codersdkretentionconfig)                                                 | false    |              |                                                                           |
| `scim_api_key`                                 | string                                                                                               | false    |              |                                                                           |
| `scim_use_legacy`                              | boolean                                                                                              | false    |              |                                                                           |
| `session_lifetime`                             | [codersdk.SessionLifetime](#codersdksessionlifetime)                                                 | false    |              |                                                                           |
| `ssh_keygen_algorithm`                         | string                                                                                               | false    |              |                                                                           |
| `stats_collection`                             | [codersdk.StatsCollectionConfig](#codersdkstatscollectionconfig)                                     | false    |              |                                                                           |
| `strict_transport_security`                    | integer                                                                                              | false    |              |                                                                           |
| `strict_transport_security_options`            | array of string                                                                                      | false    |              |                                                                           |
| `support`                                      | [codersdk.SupportConfig](#codersdksupportconfig)                                                     | false    |              |                                                                           |
| `swagger`                                      | [codersdk.SwaggerConfig](#codersdkswaggerconfig)                                                     | false    |              |                                                                           |
| `telemetry`                                    | [codersdk.TelemetryConfig](#codersdktelemetryconfig)                                                 | false    |              |                                                                           |
| `template_builder`                             | [codersdk.TemplateBuilderConfig](#codersdktemplatebuilderconfig)                                     | false    |              |                                                                           |
| `terms_of_service_url`                         | string                                                                                               | false    |              |                                                                           |
| `tls`                                          | [codersdk.TLSConfig](#codersdktlsconfig)                                                             | false    |              |                                                                           |
| `trace`                                        | [codersdk.TraceConfig](#codersdktraceconfig)                                                         | false    |              |                                                                           |
| `update_check`                                 | boolean                                                                                              | false    |              |                                                                           |
| `user_quiet_hours_schedule`                    | [codersdk.UserQuietHoursScheduleConfig](#codersdkuserquiethoursscheduleconfig)                       | false    |              |                                                                           |
| `verbose`                                      | boolean                                                                                              | false    |              |                                                                           |
| `web_terminal_renderer`                        | string                                                                                               | false    |              |                                                                           |
| `wgtunnel_host`                                | string                                                                                               | false    |              |                                                                           |
| `wildcard_access_url`                          | string                                                                                               | false    |              |                                                                           |
| `workspace_hostname_suffix`                    | string                                                                                               | false    |              |                                                                           |
| `workspace_prebuilds`                          | [codersdk.PrebuildsConfig](#codersdkprebuildsconfig)                                                 | false    |              |                                                                           |
| `write_config`                                 | boolean                                                                                              | false    |              |                                                                           |

## codersdk.DiagnosticExtra

```json
{
  "code": "string"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description |
|--------|--------|----------|--------------|-------------|
| `code` | string | false    |              |             |

## codersdk.DiagnosticSeverityString

```json
"error"
```

### Properties

#### Enumerated Values

| Value(s)           |
|--------------------|
| `error`, `warning` |

## codersdk.DisplayApp

```json
"vscode"
```

### Properties

#### Enumerated Values

| Value(s)                                                                            |
|-------------------------------------------------------------------------------------|
| `port_forwarding_helper`, `ssh_helper`, `vscode`, `vscode_insiders`, `web_terminal` |

## codersdk.DynamicParametersRequest

```json
{
  "id": 0,
  "inputs": {
    "property1": "string",
    "property2": "string"
  },
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05"
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description                                                                                                  |
|--------------------|---------|----------|--------------|--------------------------------------------------------------------------------------------------------------|
| `id`               | integer | false    |              | ID identifies the request. The response contains the same ID so that the client can match it to the request. |
| `inputs`           | object  | false    |              |                                                                                                              |
| » `[any property]` | string  | false    |              |                                                                                                              |
| `owner_id`         | string  | false    |              | Owner ID if uuid.Nil, it defaults to `codersdk.Me`                                                           |

## codersdk.DynamicParametersResponse

```json
{
  "diagnostics": [
    {
      "detail": "string",
      "extra": {
        "code": "string"
      },
      "severity": "error",
      "summary": "string"
    }
  ],
  "id": 0,
  "parameters": [
    {
      "default_value": {
        "valid": true,
        "value": "string"
      },
      "description": "string",
      "diagnostics": [
        {
          "detail": "string",
          "extra": {
            "code": "string"
          },
          "severity": "error",
          "summary": "string"
        }
      ],
      "display_name": "string",
      "ephemeral": true,
      "form_type": "",
      "icon": "string",
      "mutable": true,
      "name": "string",
      "options": [
        {
          "description": "string",
          "icon": "string",
          "name": "string",
          "value": {
            "valid": true,
            "value": "string"
          }
        }
      ],
      "order": 0,
      "required": true,
      "styling": {
        "disabled": true,
        "label": "string",
        "mask_input": true,
        "placeholder": "string"
      },
      "type": "string",
      "validations": [
        {
          "validation_error": "string",
          "validation_max": 0,
          "validation_min": 0,
          "validation_monotonic": "string",
          "validation_regex": "string"
        }
      ],
      "value": {
        "valid": true,
        "value": "string"
      }
    }
  ]
}
```

### Properties

| Name          | Type                                                                | Required | Restrictions | Description |
|---------------|---------------------------------------------------------------------|----------|--------------|-------------|
| `diagnostics` | array of [codersdk.FriendlyDiagnostic](#codersdkfriendlydiagnostic) | false    |              |             |
| `id`          | integer                                                             | false    |              |             |
| `parameters`  | array of [codersdk.PreviewParameter](#codersdkpreviewparameter)     | false    |              |             |

## codersdk.DynamicTool

```json
{
  "description": "string",
  "input_schema": [
    0
  ],
  "name": "string"
}
```

### Properties

| Name           | Type             | Required | Restrictions | Description                                                                                                                                  |
|----------------|------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------|
| `description`  | string           | false    |              |                                                                                                                                              |
| `input_schema` | array of integer | false    |              | Input schema JSON key "input_schema" uses snake_case for SDK consistency, deviating from the camelCase "inputSchema" convention used by MCP. |
| `name`         | string           | false    |              |                                                                                                                                              |

## codersdk.EditChatMessageRequest

```json
{
  "content": [
    {
      "content": "string",
      "end_line": 0,
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "file_name": "string",
      "start_line": 0,
      "text": "string",
      "type": "text",
      "workspace_file_media_type": "string",
      "workspace_file_name": "string",
      "workspace_file_path": "string",
      "workspace_file_size": 0,
      "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
    }
  ],
  "mcp_server_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
  "reasoning_effort": "string"
}
```

### Properties

| Name               | Type                                                      | Required | Restrictions | Description                                                                                                                                                                  |
|--------------------|-----------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `content`          | array of [codersdk.ChatInputPart](#codersdkchatinputpart) | false    |              |                                                                                                                                                                              |
| `mcp_server_ids`   | array of string                                           | false    |              | Mcp server ids when set, replaces the chat's MCP server selection before the replacement turn runs. When nil the current selection is preserved.                             |
| `model_config_id`  | string                                                    | false    |              | Model config ID when set, overrides the model used for the replacement user message and the assistant turn that follows. When nil the original message's model is preserved. |
| `reasoning_effort` | string                                                    | false    |              |                                                                                                                                                                              |

## codersdk.EditChatMessageResponse

```json
{
  "deleted_message_ids": [
    0
  ],
  "message": {
    "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
    "content": [
      {
        "args": [
          0
        ],
        "args_delta": "string",
        "completed_at": "2019-08-24T14:15:22Z",
        "content": "string",
        "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
        "context_file_content": "string",
        "context_file_directory": "string",
        "context_file_os": "string",
        "context_file_path": "string",
        "context_file_skill_meta_file": "string",
        "context_file_truncated": true,
        "created_at": "2019-08-24T14:15:22Z",
        "data": [
          0
        ],
        "end_line": 0,
        "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
        "file_name": "string",
        "hook_rewritten": true,
        "is_error": true,
        "is_media": true,
        "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
        "media_type": "string",
        "name": "string",
        "parsed_commands": [
          [
            "string"
          ]
        ],
        "provider_executed": true,
        "provider_metadata": [
          0
        ],
        "reasoning_delta": "string",
        "result": [
          0
        ],
        "result_delta": "string",
        "result_reset": true,
        "skill_description": "string",
        "skill_dir": "string",
        "skill_name": "string",
        "source_id": "string",
        "start_line": 0,
        "text": "string",
        "title": "string",
        "tool_call_id": "string",
        "tool_name": "string",
        "type": "text",
        "url": "string",
        "workspace_file_media_type": "string",
        "workspace_file_name": "string",
        "workspace_file_path": "string",
        "workspace_file_size": 0,
        "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
    "id": 0,
    "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
    "queued_message_id": 0,
    "role": "system",
    "usage": {
      "cache_creation_tokens": 0,
      "cache_read_tokens": 0,
      "context_limit": 0,
      "input_tokens": 0,
      "output_tokens": 0,
      "reasoning_tokens": 0,
      "total_tokens": 0
    }
  },
  "messages": [
    {
      "chat_id": "efc9fe20-a1e5-4a8c-9c48-f1b30c1e4f86",
      "content": [
        {
          "args": [
            0
          ],
          "args_delta": "string",
          "completed_at": "2019-08-24T14:15:22Z",
          "content": "string",
          "context_file_agent_id": "2e577c68-2ec9-4c84-a77a-5b3e1d7eae09",
          "context_file_content": "string",
          "context_file_directory": "string",
          "context_file_os": "string",
          "context_file_path": "string",
          "context_file_skill_meta_file": "string",
          "context_file_truncated": true,
          "created_at": "2019-08-24T14:15:22Z",
          "data": [
            0
          ],
          "end_line": 0,
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "file_name": "string",
          "hook_rewritten": true,
          "is_error": true,
          "is_media": true,
          "mcp_server_config_id": "a9f436ed-69e7-459c-8308-a67ff5387e3e",
          "media_type": "string",
          "name": "string",
          "parsed_commands": [
            [
              "string"
            ]
          ],
          "provider_executed": true,
          "provider_metadata": [
            0
          ],
          "reasoning_delta": "string",
          "result": [
            0
          ],
          "result_delta": "string",
          "result_reset": true,
          "skill_description": "string",
          "skill_dir": "string",
          "skill_name": "string",
          "source_id": "string",
          "start_line": 0,
          "text": "string",
          "title": "string",
          "tool_call_id": "string",
          "tool_name": "string",
          "type": "text",
          "url": "string",
          "workspace_file_media_type": "string",
          "workspace_file_name": "string",
          "workspace_file_path": "string",
          "workspace_file_size": 0,
          "workspace_file_workspace_id": "74c05446-1c56-4543-82a9-03f2bf73b2ab"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
      "id": 0,
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
      "queued_message_id": 0,
      "role": "system",
      "usage": {
        "cache_creation_tokens": 0,
        "cache_read_tokens": 0,
        "context_limit": 0,
        "input_tokens": 0,
        "output_tokens": 0,
        "reasoning_tokens": 0,
        "total_tokens": 0
      }
    }
  ],
  "warnings": [
    "string"
  ]
}
```

### Properties

| Name                  | Type                                                  | Required | Restrictions | Description                                                                                                                                                                       |
|-----------------------|-------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `deleted_message_ids` | array of integer                                      | false    |              | Deleted message ids holds the IDs of previously visible messages the edit removed, including stale hook notices from the edited turn. Clients should drop them from local caches. |
| `message`             | [codersdk.ChatMessage](#codersdkchatmessage)          | false    |              |                                                                                                                                                                                   |
| `messages`            | array of [codersdk.ChatMessage](#codersdkchatmessage) | false    |              | Messages holds every user-visible message inserted by the edit, in insertion order. Hook-generated suffix messages may follow Message, so clients must upsert the full batch.     |
| `warnings`            | array of string                                       | false    |              |                                                                                                                                                                                   |

## codersdk.Entitlement

```json
"entitled"
```

### Properties

#### Enumerated Values

| Value(s)                                   |
|--------------------------------------------|
| `entitled`, `grace_period`, `not_entitled` |

## codersdk.Entitlements

```json
{
  "errors": [
    "string"
  ],
  "features": {
    "property1": {
      "actual": 0,
      "actual_ms": 0,
      "enabled": true,
      "entitlement": "entitled",
      "hard_limit": 0,
      "limit": 0,
      "soft_limit": 0,
      "usage_period": {
        "end": "2019-08-24T14:15:22Z",
        "issued_at": "2019-08-24T14:15:22Z",
        "start": "2019-08-24T14:15:22Z"
      }
    },
    "property2": {
      "actual": 0,
      "actual_ms": 0,
      "enabled": true,
      "entitlement": "entitled",
      "hard_limit": 0,
      "limit": 0,
      "soft_limit": 0,
      "usage_period": {
        "end": "2019-08-24T14:15:22Z",
        "issued_at": "2019-08-24T14:15:22Z",
        "start": "2019-08-24T14:15:22Z"
      }
    }
  },
  "has_license": true,
  "refreshed_at": "2019-08-24T14:15:22Z",
  "require_telemetry": true,
  "trial": true,
  "warnings": [
    "string"
  ]
}
```

### Properties

| Name                | Type                                 | Required | Restrictions | Description |
|---------------------|--------------------------------------|----------|--------------|-------------|
| `errors`            | array of string                      | false    |              |             |
| `features`          | object                               | false    |              |             |
| » `[any property]`  | [codersdk.Feature](#codersdkfeature) | false    |              |             |
| `has_license`       | boolean                              | false    |              |             |
| `refreshed_at`      | string                               | false    |              |             |
| `require_telemetry` | boolean                              | false    |              |             |
| `trial`             | boolean                              | false    |              |             |
| `warnings`          | array of string                      | false    |              |             |

## codersdk.Experiment

```json
"example"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                                                                                                                                                                                                                                |
|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent-lifecycle-hooks`, `ai-gateway-reverse-proxy`, `ai-gateway-seat-exclusion`, `auto-fill-parameters`, `chat-advisor`, `chat-board`, `chat-inline-mcp-servers`, `chat-virtual-desktop`, `enable-ai-workspace-debug`, `example`, `mcp-server-http`, `mcp-tool-search`, `no_nats_pubsub`, `notifications`, `workspace-build-updates`, `workspace-capable-licensing`, `workspace-usage` |

## codersdk.ExperimentRule

```json
{
  "condition": "string",
  "mode": "string",
  "revision": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "updated_by": "deea00dc-b6b6-4412-a483-26ac61e1f6fe"
}
```

### Properties

| Name         | Type    | Required | Restrictions | Description                                                                                                                                                                                                          |
|--------------|---------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `condition`  | string  | false    |              | Condition is the CEL expression of a condition rule.                                                                                                                                                                 |
| `mode`       | string  | false    |              | Mode is one of the ExperimentRuleMode values, or empty when the stored rule is malformed. A malformed rule decides off until it is replaced. It is a plain string so that clients can represent the malformed state. |
| `revision`   | integer | false    |              | Revision increases on every change and starts at 1. Zero means the stored rule has no readable positive revision, so it is malformed.                                                                                |
| `updated_at` | string  | false    |              |                                                                                                                                                                                                                      |
| `updated_by` | string  | false    |              |                                                                                                                                                                                                                      |

## codersdk.ExperimentRuleEntry

```json
{
  "experiment": "string",
  "ignored": true,
  "rule": {
    "condition": "string",
    "mode": "string",
    "revision": 0,
    "updated_at": "2019-08-24T14:15:22Z",
    "updated_by": "deea00dc-b6b6-4412-a483-26ac61e1f6fe"
  },
  "static_default": true
}
```

### Properties

| Name             | Type                                               | Required | Restrictions | Description                                                                                                                  |
|------------------|----------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------|
| `experiment`     | string                                             | false    |              | Experiment is the experiment name. Ignored entries can name experiments this version does not know, so it is a plain string. |
| `ignored`        | boolean                                            | false    |              | Ignored is true for a stored rule of an experiment that does not accept runtime rules. Such a rule has no effect.            |
| `rule`           | [codersdk.ExperimentRule](#codersdkexperimentrule) | false    |              | Rule is null when no rule was ever stored.                                                                                   |
| `static_default` | boolean                                            | false    |              | Static default reports whether the experiment is in the startup --experiments list of the replica that answered.             |

## codersdk.ExperimentRuleMode

```json
"inherit"
```

### Properties

#### Enumerated Values

| Value(s)                            |
|-------------------------------------|
| `condition`, `inherit`, `off`, `on` |

## codersdk.ExternalAPIKeyScopes

```json
{
  "external": [
    "all"
  ]
}
```

### Properties

| Name       | Type                                                  | Required | Restrictions | Description |
|------------|-------------------------------------------------------|----------|--------------|-------------|
| `external` | array of [codersdk.APIKeyScope](#codersdkapikeyscope) | false    |              |             |

## codersdk.ExternalAgentCredentials

```json
{
  "agent_token": "string",
  "command": "string"
}
```

### Properties

| Name          | Type   | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `agent_token` | string | false    |              |             |
| `command`     | string | false    |              |             |

## codersdk.ExternalAuth

```json
{
  "app_install_url": "string",
  "app_installable": true,
  "authenticated": true,
  "device": true,
  "display_name": "string",
  "installations": [
    {
      "account": {
        "avatar_url": "string",
        "id": 0,
        "login": "string",
        "name": "string",
        "profile_url": "string"
      },
      "configure_url": "string",
      "id": 0
    }
  ],
  "supports_revocation": true,
  "user": {
    "avatar_url": "string",
    "id": 0,
    "login": "string",
    "name": "string",
    "profile_url": "string"
  }
}
```

### Properties

| Name                  | Type                                                                                  | Required | Restrictions | Description                                                             |
|-----------------------|---------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------|
| `app_install_url`     | string                                                                                | false    |              | App install URL is the URL to install the app.                          |
| `app_installable`     | boolean                                                                               | false    |              | App installable is true if the request for app installs was successful. |
| `authenticated`       | boolean                                                                               | false    |              |                                                                         |
| `device`              | boolean                                                                               | false    |              |                                                                         |
| `display_name`        | string                                                                                | false    |              |                                                                         |
| `installations`       | array of [codersdk.ExternalAuthAppInstallation](#codersdkexternalauthappinstallation) | false    |              | Installations are the installations that the user has access to.        |
| `supports_revocation` | boolean                                                                               | false    |              |                                                                         |
| `user`                | [codersdk.ExternalAuthUser](#codersdkexternalauthuser)                                | false    |              | User is the user that authenticated with the provider.                  |

## codersdk.ExternalAuthAppInstallation

```json
{
  "account": {
    "avatar_url": "string",
    "id": 0,
    "login": "string",
    "name": "string",
    "profile_url": "string"
  },
  "configure_url": "string",
  "id": 0
}
```

### Properties

| Name            | Type                                                   | Required | Restrictions | Description |
|-----------------|--------------------------------------------------------|----------|--------------|-------------|
| `account`       | [codersdk.ExternalAuthUser](#codersdkexternalauthuser) | false    |              |             |
| `configure_url` | string                                                 | false    |              |             |
| `id`            | integer                                                | false    |              |             |

## codersdk.ExternalAuthConfig

```json
{
  "api_base_url": "string",
  "app_install_url": "string",
  "app_installations_url": "string",
  "auth_url": "string",
  "client_id": "string",
  "code_challenge_methods_supported": [
    "string"
  ],
  "device_code_url": "string",
  "device_flow": true,
  "display_icon": "string",
  "display_name": "string",
  "id": "string",
  "mcp_tool_allow_regex": "string",
  "mcp_tool_deny_regex": "string",
  "mcp_url": "string",
  "no_refresh": true,
  "redirect_url": "string",
  "regex": "string",
  "revoke_url": "string",
  "scopes": [
    "string"
  ],
  "token_url": "string",
  "type": "string",
  "validate_url": "string"
}
```

### Properties

| Name                               | Type            | Required | Restrictions | Description                                                                                                                                                                                   |
|------------------------------------|-----------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api_base_url`                     | string          | false    |              | Api base URL is the base URL for provider REST API calls (e.g., "https://api.github.com" for GitHub). Derived from defaults when not explicitly configured.                                   |
| `app_install_url`                  | string          | false    |              |                                                                                                                                                                                               |
| `app_installations_url`            | string          | false    |              |                                                                                                                                                                                               |
| `auth_url`                         | string          | false    |              |                                                                                                                                                                                               |
| `client_id`                        | string          | false    |              |                                                                                                                                                                                               |
| `code_challenge_methods_supported` | array of string | false    |              | Code challenge methods supported lists the PKCE code challenge methods The only one supported by Coder is "S256".                                                                             |
| `device_code_url`                  | string          | false    |              |                                                                                                                                                                                               |
| `device_flow`                      | boolean         | false    |              |                                                                                                                                                                                               |
| `display_icon`                     | string          | false    |              | Display icon is a URL to an icon to display in the UI.                                                                                                                                        |
| `display_name`                     | string          | false    |              | Display name is shown in the UI to identify the auth config.                                                                                                                                  |
| `id`                               | string          | false    |              | ID is a unique identifier for the auth config. It defaults to `type` when not provided.                                                                                                       |
| `mcp_tool_allow_regex`             | string          | false    |              | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release.                                                                                                  |
| `mcp_tool_deny_regex`              | string          | false    |              | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release.                                                                                                  |
| `mcp_url`                          | string          | false    |              | Deprecated: Injected MCP in AI Bridge is deprecated and will be removed in a future release.                                                                                                  |
| `no_refresh`                       | boolean         | false    |              |                                                                                                                                                                                               |
| `redirect_url`                     | string          | false    |              | Redirect URL is optional, defaulting to 'ACCESS_URL'. Only useful in niche situations where the OAuth callback domain is different from the ACCESS_URL domain. The path component is ignored. |
|`regex`|string|false||Regex allows API requesters to match an auth config by a string (e.g. coder.com) instead of by it's type.
Git clone makes use of this by parsing the URL from: 'Username for "https://github.com":' And sending it to the control plane to match against the Regex.|
|`revoke_url`|string|false|||
|`scopes`|array of string|false|||
|`token_url`|string|false|||
|`type`|string|false||Type is the type of external auth config.|
|`validate_url`|string|false|||

## codersdk.ExternalAuthDevice

```json
{
  "device_code": "string",
  "expires_in": 0,
  "interval": 0,
  "user_code": "string",
  "verification_uri": "string"
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description |
|--------------------|---------|----------|--------------|-------------|
| `device_code`      | string  | false    |              |             |
| `expires_in`       | integer | false    |              |             |
| `interval`         | integer | false    |              |             |
| `user_code`        | string  | false    |              |             |
| `verification_uri` | string  | false    |              |             |

## codersdk.ExternalAuthLink

```json
{
  "authenticated": true,
  "created_at": "2019-08-24T14:15:22Z",
  "expires": "2019-08-24T14:15:22Z",
  "has_refresh_token": true,
  "provider_id": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "validate_error": "string"
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `authenticated`     | boolean | false    |              |             |
| `created_at`        | string  | false    |              |             |
| `expires`           | string  | false    |              |             |
| `has_refresh_token` | boolean | false    |              |             |
| `provider_id`       | string  | false    |              |             |
| `updated_at`        | string  | false    |              |             |
| `validate_error`    | string  | false    |              |             |

## codersdk.ExternalAuthUser

```json
{
  "avatar_url": "string",
  "id": 0,
  "login": "string",
  "name": "string",
  "profile_url": "string"
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `avatar_url`  | string  | false    |              |             |
| `id`          | integer | false    |              |             |
| `login`       | string  | false    |              |             |
| `name`        | string  | false    |              |             |
| `profile_url` | string  | false    |              |             |

## codersdk.Feature

```json
{
  "actual": 0,
  "actual_ms": 0,
  "enabled": true,
  "entitlement": "entitled",
  "hard_limit": 0,
  "limit": 0,
  "soft_limit": 0,
  "usage_period": {
    "end": "2019-08-24T14:15:22Z",
    "issued_at": "2019-08-24T14:15:22Z",
    "start": "2019-08-24T14:15:22Z"
  }
}
```

### Properties

| Name           | Type                                         | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
|----------------|----------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `actual`       | integer                                      | false    |              | Actual is the usage measured against Limit, when known: a point-in-time count for most features, or usage accumulated over UsagePeriod for features that set one. Its unit matches Limit's; FeatureAgentRuntimeHours reports whole hours floored from the recorded milliseconds, with the precise value available in ActualMs. FeatureAgentRuntimeHours usage can trail by roughly one hour because the current hour is not emitted, plus the entitlement refresh interval. |
| `actual_ms`    | integer                                      | false    |              | Actual ms is the precise usage backing Actual, in milliseconds, for features measured in time. It has the same freshness as Actual. Only FeatureAgentRuntimeHours sets this field.                                                                                                                                                                                                                                                                                          |
| `enabled`      | boolean                                      | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `entitlement`  | [codersdk.Entitlement](#codersdkentitlement) | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `hard_limit`   | integer                                      | false    |              | Hard limit is the enforcement threshold that accompanies Limit for features whose license carries it. See SoftLimit for the set of features that use these thresholds.                                                                                                                                                                                                                                                                                                      |
| `limit`        | integer                                      | false    |              | Limit is the maximum value the license grants for the feature, in the feature's own unit. For FeatureAgentRuntimeHours, an enabled feature with Limit omitted means the license grants unlimited runtime hours.                                                                                                                                                                                                                                                             |
| `soft_limit`   | integer                                      | false    |              | Soft limit is the advisory warning threshold that accompanies Limit for features whose license carries it. For these features, Limit carries the purchased allocation; an unlimited allocation has no thresholds, so SoftLimit is omitted alongside the omitted Limit. Only FeatureAgentRuntimeHours sets this field.                                                                                                                                                       |
| `usage_period` | [codersdk.UsagePeriod](#codersdkusageperiod) | false    |              | Usage period denotes that the usage is a counter that accumulates over this period (and most likely resets with the issuance of the next license). These dates are determined from the license that this entitlement comes from, see enterprise/coderd/license/license.go. Only FeatureManagedAgentLimit and FeatureAgentRuntimeHours set this field.                                                                                                                       |

## codersdk.FriendlyDiagnostic

```json
{
  "detail": "string",
  "extra": {
    "code": "string"
  },
  "severity": "error",
  "summary": "string"
}
```

### Properties

| Name       | Type                                                                   | Required | Restrictions | Description |
|------------|------------------------------------------------------------------------|----------|--------------|-------------|
| `detail`   | string                                                                 | false    |              |             |
| `extra`    | [codersdk.DiagnosticExtra](#codersdkdiagnosticextra)                   | false    |              |             |
| `severity` | [codersdk.DiagnosticSeverityString](#codersdkdiagnosticseveritystring) | false    |              |             |
| `summary`  | string                                                                 | false    |              |             |

## codersdk.GenerateAPIKeyResponse

```json
{
  "key": "string"
}
```

### Properties

| Name  | Type   | Required | Restrictions | Description |
|-------|--------|----------|--------------|-------------|
| `key` | string | false    |              |             |

## codersdk.GetInboxNotificationResponse

```json
{
  "notification": {
    "actions": [
      {
        "label": "string",
        "url": "string"
      }
    ],
    "content": "string",
    "created_at": "2019-08-24T14:15:22Z",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "read_at": "string",
    "targets": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
    "title": "string",
    "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
  },
  "unread_count": 0
}
```

### Properties

| Name           | Type                                                     | Required | Restrictions | Description |
|----------------|----------------------------------------------------------|----------|--------------|-------------|
| `notification` | [codersdk.InboxNotification](#codersdkinboxnotification) | false    |              |             |
| `unread_count` | integer                                                  | false    |              |             |

## codersdk.GetUserStatusCountsResponse

```json
{
  "status_counts": {
    "property1": [
      {
        "count": 10,
        "date": "2019-08-24T14:15:22Z"
      }
    ],
    "property2": [
      {
        "count": 10,
        "date": "2019-08-24T14:15:22Z"
      }
    ]
  }
}
```

### Properties

| Name               | Type                                                                      | Required | Restrictions | Description |
|--------------------|---------------------------------------------------------------------------|----------|--------------|-------------|
| `status_counts`    | object                                                                    | false    |              |             |
| » `[any property]` | array of [codersdk.UserStatusChangeCount](#codersdkuserstatuschangecount) | false    |              |             |

## codersdk.GetUsersResponse

```json
{
  "count": 0,
  "users": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "has_ai_seat": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "organization_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "roles": [
        {
          "display_name": "string",
          "name": "string",
          "organization_id": "string"
        }
      ],
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Properties

| Name    | Type                                    | Required | Restrictions | Description |
|---------|-----------------------------------------|----------|--------------|-------------|
| `count` | integer                                 | false    |              |             |
| `users` | array of [codersdk.User](#codersdkuser) | false    |              |             |

## codersdk.GitSSHKey

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "public_key": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description                                                                                                                                                                                       |
|--------------|--------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `created_at` | string | false    |              |                                                                                                                                                                                                   |
| `public_key` | string | false    |              | Public key is the SSH public key in OpenSSH format. Example: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID3OmYJvT7q1cF1azbybYy0OZ9yrXfA+M6Lr4vzX5zlp\n" Note: The key includes a trailing newline (\n). |
| `updated_at` | string | false    |              |                                                                                                                                                                                                   |
| `user_id`    | string | false    |              |                                                                                                                                                                                                   |

## codersdk.GithubAuthMethod

```json
{
  "default_provider_configured": true,
  "enabled": true
}
```

### Properties

| Name                          | Type    | Required | Restrictions | Description |
|-------------------------------|---------|----------|--------------|-------------|
| `default_provider_configured` | boolean | false    |              |             |
| `enabled`                     | boolean | false    |              |             |

## codersdk.Group

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "source": "user",
  "total_member_count": 0
}
```

### Properties

| Name                        | Type                                                  | Required | Restrictions | Description                                                                                                                                                           |
|-----------------------------|-------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `avatar_url`                | string                                                | false    |              |                                                                                                                                                                       |
| `display_name`              | string                                                | false    |              |                                                                                                                                                                       |
| `id`                        | string                                                | false    |              |                                                                                                                                                                       |
| `members`                   | array of [codersdk.ReducedUser](#codersdkreduceduser) | false    |              |                                                                                                                                                                       |
| `name`                      | string                                                | false    |              |                                                                                                                                                                       |
| `organization_display_name` | string                                                | false    |              |                                                                                                                                                                       |
| `organization_id`           | string                                                | false    |              |                                                                                                                                                                       |
| `organization_name`         | string                                                | false    |              |                                                                                                                                                                       |
| `quota_allowance`           | integer                                               | false    |              |                                                                                                                                                                       |
| `source`                    | [codersdk.GroupSource](#codersdkgroupsource)          | false    |              |                                                                                                                                                                       |
| `total_member_count`        | integer                                               | false    |              | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. |

## codersdk.GroupAIBudget

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `created_at`         | string  | false    |              |             |
| `group_id`           | string  | false    |              |             |
| `spend_limit_micros` | integer | false    |              |             |
| `updated_at`         | string  | false    |              |             |

## codersdk.GroupAISpend

```json
{
  "current_spend_micros": 0,
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z",
  "spend_limit_micros": 0,
  "total_spend_limit_micros": 0
}
```

### Properties

| Name                       | Type    | Required | Restrictions | Description                                                                                                                                                                                                                                        |
|----------------------------|---------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `current_spend_micros`     | integer | false    |              | Current spend micros is the group's spend over the current budget period.                                                                                                                                                                          |
| `group_id`                 | string  | false    |              |                                                                                                                                                                                                                                                    |
| `period_end`               | string  | false    |              | Period end is the exclusive upper bound of the current budget period.                                                                                                                                                                              |
| `period_start`             | string  | false    |              | Period start is the inclusive lower bound of the current budget period.                                                                                                                                                                            |
| `spend_limit_micros`       | integer | false    |              | Spend limit micros is the group's configured AI spend budget per member. Null when the group has no configured budget.                                                                                                                             |
| `total_spend_limit_micros` | integer | false    |              | Total spend limit micros is the currently configured combined budget of the members attributed to this group, with each member's override replacing their share. Null when the group has no budget, and zero when no members are attributed to it. |

## codersdk.GroupMemberAISpend

```json
{
  "effective_budget": {
    "limit_source": "user_override",
    "spend_limit_micros": 0
  },
  "effective_group_id": "85e2b926-ddfb-4c66-b68e-b66e5acec6c0",
  "group_budget": {
    "limit_source": "user_override",
    "spend_limit_micros": 0
  },
  "group_spend_micros": 0,
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name                 | Type                                             | Required | Restrictions | Description                                                                                                                                                                                                                                                |
|----------------------|--------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `effective_budget`   | [codersdk.AIBudgetLimit](#codersdkaibudgetlimit) | false    |              | Effective budget is the spend limit that currently applies to the user. Null when no budget applies or the effective group belongs to a different organization than the queried group.                                                                     |
| `effective_group_id` | string                                           | false    |              | Effective group ID is the user's effective budget group within the queried group's organization, falling back to the Everyone group when no budget applies. Null when the effective group belongs to a different organization than the queried group.      |
| `group_budget`       | [codersdk.AIBudgetLimit](#codersdkaibudgetlimit) | false    |              | Group budget is the budget when the queried group is this user's effective budget source. When populated, it matches EffectiveBudget. Null when the user's budget resolves to another group or no budget applies. Deprecated: Use EffectiveBudget instead. |
| `group_spend_micros` | integer                                          | false    |              | Group spend micros is the user's spend attributed to the queried group over the current budget period.                                                                                                                                                     |
| `user_id`            | string                                           | false    |              |                                                                                                                                                                                                                                                            |

## codersdk.GroupMembersAISpend

```json
{
  "members": [
    {
      "effective_budget": {
        "limit_source": "user_override",
        "spend_limit_micros": 0
      },
      "effective_group_id": "85e2b926-ddfb-4c66-b68e-b66e5acec6c0",
      "group_budget": {
        "limit_source": "user_override",
        "spend_limit_micros": 0
      },
      "group_spend_micros": 0,
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
    }
  ],
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name           | Type                                                                | Required | Restrictions | Description                                                             |
|----------------|---------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------|
| `members`      | array of [codersdk.GroupMemberAISpend](#codersdkgroupmemberaispend) | false    |              |                                                                         |
| `period_end`   | string                                                              | false    |              | Period end is the exclusive upper bound of the current budget period.   |
| `period_start` | string                                                              | false    |              | Period start is the inclusive lower bound of the current budget period. |

## codersdk.GroupMembersResponse

```json
{
  "count": 0,
  "users": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Properties

| Name    | Type                                                  | Required | Restrictions | Description |
|---------|-------------------------------------------------------|----------|--------------|-------------|
| `count` | integer                                               | false    |              |             |
| `users` | array of [codersdk.ReducedUser](#codersdkreduceduser) | false    |              |             |

## codersdk.GroupSource

```json
"user"
```

### Properties

#### Enumerated Values

| Value(s)       |
|----------------|
| `oidc`, `user` |

## codersdk.GroupSyncSettings

```json
{
  "auto_create_missing_groups": true,
  "field": "string",
  "legacy_group_name_mapping": {
    "property1": "string",
    "property2": "string"
  },
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "regex_filter": {}
}
```

### Properties

| Name                         | Type                           | Required | Restrictions | Description                                                                                                                                                                                                                                                                            |
|------------------------------|--------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `auto_create_missing_groups` | boolean                        | false    |              | Auto create missing groups controls whether groups returned by the OIDC provider are automatically created in Coder if they are missing.                                                                                                                                               |
| `field`                      | string                         | false    |              | Field is the name of the claim field that specifies what groups a user should be in. If empty, no groups will be synced.                                                                                                                                                               |
| `legacy_group_name_mapping`  | object                         | false    |              | Legacy group name mapping is deprecated. It remaps an IDP group name to a Coder group name. Since configuration is now done at runtime, group IDs are used to account for group renames. For legacy configurations, this config option has to remain. Deprecated: Use Mapping instead. |
| » `[any property]`           | string                         | false    |              |                                                                                                                                                                                                                                                                                        |
| `mapping`                    | object                         | false    |              | Mapping is a map from OIDC groups to Coder group IDs                                                                                                                                                                                                                                   |
| » `[any property]`           | array of string                | false    |              |                                                                                                                                                                                                                                                                                        |
| `regex_filter`               | [regexp.Regexp](#regexpregexp) | false    |              | Regex filter is a regular expression that filters the groups returned by the OIDC provider. Any group not matched by this regex will be ignored. If the group filter is nil, then no group filtering will occur.                                                                       |

## codersdk.HTTPCookieConfig

```json
{
  "host_prefix": true,
  "same_site": "string",
  "secure_auth_cookie": true
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `host_prefix`        | boolean | false    |              |             |
| `same_site`          | string  | false    |              |             |
| `secure_auth_cookie` | boolean | false    |              |             |

## codersdk.Healthcheck

```json
{
  "interval": 0,
  "threshold": 0,
  "url": "string"
}
```

### Properties

| Name        | Type    | Required | Restrictions | Description                                                                                      |
|-------------|---------|----------|--------------|--------------------------------------------------------------------------------------------------|
| `interval`  | integer | false    |              | Interval specifies the seconds between each health check.                                        |
| `threshold` | integer | false    |              | Threshold specifies the number of consecutive failed health checks before returning "unhealthy". |
| `url`       | string  | false    |              | URL specifies the endpoint to check for the app health.                                          |

## codersdk.HealthcheckConfig

```json
{
  "refresh": 0,
  "threshold_database": 0
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `refresh`            | integer | false    |              |             |
| `threshold_database` | integer | false    |              |             |

## codersdk.ImportUserSecretsRequest

```json
{
  "content": "string",
  "format": "env"
}
```

### Properties

| Name      | Type                                                     | Required | Restrictions | Description |
|-----------|----------------------------------------------------------|----------|--------------|-------------|
| `content` | string                                                   | true     |              |             |
| `format`  | [codersdk.SecretsFileFormat](#codersdksecretsfileformat) | true     |              |             |

## codersdk.InboxNotification

```json
{
  "actions": [
    {
      "label": "string",
      "url": "string"
    }
  ],
  "content": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "read_at": "string",
  "targets": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "title": "string",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name          | Type                                                                          | Required | Restrictions | Description |
|---------------|-------------------------------------------------------------------------------|----------|--------------|-------------|
| `actions`     | array of [codersdk.InboxNotificationAction](#codersdkinboxnotificationaction) | false    |              |             |
| `content`     | string                                                                        | false    |              |             |
| `created_at`  | string                                                                        | false    |              |             |
| `icon`        | string                                                                        | false    |              |             |
| `id`          | string                                                                        | false    |              |             |
| `read_at`     | string                                                                        | false    |              |             |
| `targets`     | array of string                                                               | false    |              |             |
| `template_id` | string                                                                        | false    |              |             |
| `title`       | string                                                                        | false    |              |             |
| `user_id`     | string                                                                        | false    |              |             |

## codersdk.InboxNotificationAction

```json
{
  "label": "string",
  "url": "string"
}
```

### Properties

| Name    | Type   | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `label` | string | false    |              |             |
| `url`   | string | false    |              |             |

## codersdk.InlineMCPServer

```json
{
  "allow_in_subagents": true,
  "created_at": "2019-08-24T14:15:22Z",
  "forward_coder_headers": true,
  "has_custom_headers": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "slug": "string",
  "tool_allow_list": [
    "string"
  ],
  "tool_deny_list": [
    "string"
  ],
  "updated_at": "2019-08-24T14:15:22Z",
  "url": "string"
}
```

### Properties

| Name                    | Type            | Required | Restrictions | Description                                           |
|-------------------------|-----------------|----------|--------------|-------------------------------------------------------|
| `allow_in_subagents`    | boolean         | false    |              |                                                       |
| `created_at`            | string          | false    |              |                                                       |
| `forward_coder_headers` | boolean         | false    |              |                                                       |
| `has_custom_headers`    | boolean         | false    |              |                                                       |
| `id`                    | string          | false    |              |                                                       |
| `slug`                  | string          | false    |              |                                                       |
| `tool_allow_list`       | array of string | false    |              |                                                       |
| `tool_deny_list`        | array of string | false    |              |                                                       |
| `updated_at`            | string          | false    |              |                                                       |
| `url`                   | string          | false    |              | URL is empty unless the chat owner makes the request. |

## codersdk.InlineMCPServerRequest

```json
{
  "allow_in_subagents": true,
  "forward_coder_headers": true,
  "headers": {
    "property1": "string",
    "property2": "string"
  },
  "slug": "string",
  "tool_allow_list": [
    "string"
  ],
  "tool_deny_list": [
    "string"
  ],
  "url": "string"
}
```

### Properties

| Name                    | Type            | Required | Restrictions | Description |
|-------------------------|-----------------|----------|--------------|-------------|
| `allow_in_subagents`    | boolean         | false    |              |             |
| `forward_coder_headers` | boolean         | false    |              |             |
| `headers`               | object          | false    |              |             |
| » `[any property]`      | string          | false    |              |             |
| `slug`                  | string          | false    |              |             |
| `tool_allow_list`       | array of string | false    |              |             |
| `tool_deny_list`        | array of string | false    |              |             |
| `url`                   | string          | false    |              |             |

## codersdk.InsightsReportInterval

```json
"day"
```

### Properties

#### Enumerated Values

| Value(s)      |
|---------------|
| `day`, `week` |

## codersdk.InvalidatePresetsResponse

```json
{
  "invalidated": [
    {
      "preset_name": "string",
      "template_name": "string",
      "template_version_name": "string"
    }
  ]
}
```

### Properties

| Name          | Type                                                              | Required | Restrictions | Description |
|---------------|-------------------------------------------------------------------|----------|--------------|-------------|
| `invalidated` | array of [codersdk.InvalidatedPreset](#codersdkinvalidatedpreset) | false    |              |             |

## codersdk.InvalidatedPreset

```json
{
  "preset_name": "string",
  "template_name": "string",
  "template_version_name": "string"
}
```

### Properties

| Name                    | Type   | Required | Restrictions | Description |
|-------------------------|--------|----------|--------------|-------------|
| `preset_name`           | string | false    |              |             |
| `template_name`         | string | false    |              |             |
| `template_version_name` | string | false    |              |             |

## codersdk.IssueReconnectingPTYSignedTokenRequest

```json
{
  "agentID": "bc282582-04f9-45ce-b904-3e3bfab66958",
  "url": "string"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description                                                            |
|-----------|--------|----------|--------------|------------------------------------------------------------------------|
| `agentID` | string | true     |              |                                                                        |
| `url`     | string | true     |              | URL is the URL of the reconnecting-pty endpoint you are connecting to. |

## codersdk.IssueReconnectingPTYSignedTokenResponse

```json
{
  "signed_token": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `signed_token` | string | false    |              |             |

## codersdk.JobErrorCode

```json
"REQUIRED_TEMPLATE_VARIABLES"
```

### Properties

#### Enumerated Values

| Value(s)                                            |
|-----------------------------------------------------|
| `INSUFFICIENT_QUOTA`, `REQUIRED_TEMPLATE_VARIABLES` |

## codersdk.License

```json
{
  "claims": {},
  "id": 0,
  "uploaded_at": "2019-08-24T14:15:22Z",
  "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f"
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description                                                                                                                                                                                             |
|---------------|---------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `claims`      | object  | false    |              | Claims are the JWT claims asserted by the license.  Here we use a generic string map to ensure that all data from the server is parsed verbatim, not just the fields this version of Coder understands. |
| `id`          | integer | false    |              |                                                                                                                                                                                                         |
| `uploaded_at` | string  | false    |              |                                                                                                                                                                                                         |
| `uuid`        | string  | false    |              |                                                                                                                                                                                                         |

## codersdk.LinkConfig

```json
{
  "icon": "bug",
  "location": "navbar",
  "name": "string",
  "target": "string"
}
```

### Properties

| Name       | Type   | Required | Restrictions | Description |
|------------|--------|----------|--------------|-------------|
| `icon`     | string | false    |              |             |
| `location` | string | false    |              |             |
| `name`     | string | false    |              |             |
| `target`   | string | false    |              |             |

#### Enumerated Values

| Property   | Value(s)                      |
|------------|-------------------------------|
| `icon`     | `bug`, `chat`, `docs`, `star` |
| `location` | `dropdown`, `navbar`          |

## codersdk.ListInboxNotificationsResponse

```json
{
  "notifications": [
    {
      "actions": [
        {
          "label": "string",
          "url": "string"
        }
      ],
      "content": "string",
      "created_at": "2019-08-24T14:15:22Z",
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "read_at": "string",
      "targets": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "title": "string",
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
    }
  ],
  "unread_count": 0
}
```

### Properties

| Name            | Type                                                              | Required | Restrictions | Description |
|-----------------|-------------------------------------------------------------------|----------|--------------|-------------|
| `notifications` | array of [codersdk.InboxNotification](#codersdkinboxnotification) | false    |              |             |
| `unread_count`  | integer                                                           | false    |              |             |

## codersdk.LogLevel

```json
"trace"
```

### Properties

#### Enumerated Values

| Value(s)                                  |
|-------------------------------------------|
| `debug`, `error`, `info`, `trace`, `warn` |

## codersdk.LogSource

```json
"provisioner_daemon"
```

### Properties

#### Enumerated Values

| Value(s)                            |
|-------------------------------------|
| `provisioner`, `provisioner_daemon` |

## codersdk.LoggingConfig

```json
{
  "human": "string",
  "json": "string",
  "log_filter": [
    "string"
  ],
  "stackdriver": "string"
}
```

### Properties

| Name          | Type            | Required | Restrictions | Description |
|---------------|-----------------|----------|--------------|-------------|
| `human`       | string          | false    |              |             |
| `json`        | string          | false    |              |             |
| `log_filter`  | array of string | false    |              |             |
| `stackdriver` | string          | false    |              |             |

## codersdk.LoginType

```json
""
```

### Properties

#### Enumerated Values

| Value(s)                                          |
|---------------------------------------------------|
| ``, `github`, `none`, `oidc`, `password`, `token` |

## codersdk.LoginWithPasswordRequest

```json
{
  "email": "user@example.com",
  "password": "string"
}
```

### Properties

| Name       | Type   | Required | Restrictions | Description |
|------------|--------|----------|--------------|-------------|
| `email`    | string | true     |              |             |
| `password` | string | true     |              |             |

## codersdk.LoginWithPasswordResponse

```json
{
  "session_token": "string"
}
```

### Properties

| Name            | Type   | Required | Restrictions | Description |
|-----------------|--------|----------|--------------|-------------|
| `session_token` | string | true     |              |             |

## codersdk.MCPServerConfig

```json
{
  "allow_in_plan_mode": true,
  "api_key_header": "string",
  "auth_connected": true,
  "auth_type": "string",
  "availability": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "description": "string",
  "display_name": "string",
  "enabled": true,
  "forward_coder_headers": true,
  "has_api_key": true,
  "has_custom_headers": true,
  "has_oauth2_secret": true,
  "has_signing_secret": true,
  "icon_url": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "model_intent": true,
  "oauth2_auth_url": "string",
  "oauth2_client_id": "string",
  "oauth2_revocation_url": "string",
  "oauth2_scopes": "string",
  "oauth2_token_url": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "slug": "string",
  "tool_allow_list": [
    "string"
  ],
  "tool_deny_list": [
    "string"
  ],
  "transport": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "url": "string"
}
```

### Properties

| Name                    | Type            | Required | Restrictions | Description                                                                                                                                                                                                                                                                                          |
|-------------------------|-----------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `allow_in_plan_mode`    | boolean         | false    |              |                                                                                                                                                                                                                                                                                                      |
| `api_key_header`        | string          | false    |              | Api key header key fields (only populated for admins).                                                                                                                                                                                                                                               |
| `auth_connected`        | boolean         | false    |              | Per-user state (populated for non-admin requests).                                                                                                                                                                                                                                                   |
| `auth_type`             | string          | false    |              | "none", "oauth2", "api_key", "custom_headers", "user_oidc"                                                                                                                                                                                                                                           |
| `availability`          | string          | false    |              | Availability policy set by admin.                                                                                                                                                                                                                                                                    |
| `created_at`            | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `description`           | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `display_name`          | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `enabled`               | boolean         | false    |              |                                                                                                                                                                                                                                                                                                      |
| `forward_coder_headers` | boolean         | false    |              | Forward coder headers forwards the same Coder identity headers we send to LLM providers (X-Coder-Owner-Id, X-Coder-Chat-Id, and the optional X-Coder-Subchat-Id and X-Coder-Workspace-Id) to this MCP server on every request. Off by default to avoid leaking chat identity to third-party servers. |
| `has_api_key`           | boolean         | false    |              |                                                                                                                                                                                                                                                                                                      |
| `has_custom_headers`    | boolean         | false    |              |                                                                                                                                                                                                                                                                                                      |
| `has_oauth2_secret`     | boolean         | false    |              |                                                                                                                                                                                                                                                                                                      |
| `has_signing_secret`    | boolean         | false    |              |                                                                                                                                                                                                                                                                                                      |
| `icon_url`              | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `id`                    | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `model_intent`          | boolean         | false    |              |                                                                                                                                                                                                                                                                                                      |
| `oauth2_auth_url`       | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `oauth2_client_id`      | string          | false    |              | Oauth2 client ID fields (only populated for admins).                                                                                                                                                                                                                                                 |
| `oauth2_revocation_url` | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `oauth2_scopes`         | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `oauth2_token_url`      | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `organization_id`       | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `slug`                  | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `tool_allow_list`       | array of string | false    |              | Tool governance.                                                                                                                                                                                                                                                                                     |
| `tool_deny_list`        | array of string | false    |              |                                                                                                                                                                                                                                                                                                      |
| `transport`             | string          | false    |              | "streamable_http" or "sse"                                                                                                                                                                                                                                                                           |
| `updated_at`            | string          | false    |              |                                                                                                                                                                                                                                                                                                      |
| `url`                   | string          | false    |              |                                                                                                                                                                                                                                                                                                      |

## codersdk.MCPServerConfigACL

```json
{
  "groups": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "members": [
        {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        }
      ],
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "role": "read",
      "source": "user",
      "total_member_count": 0
    }
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "role": "read",
      "username": "string"
    }
  ]
}
```

### Properties

| Name     | Type                                                                    | Required | Restrictions | Description |
|----------|-------------------------------------------------------------------------|----------|--------------|-------------|
| `groups` | array of [codersdk.MCPServerConfigGroup](#codersdkmcpserverconfiggroup) | false    |              |             |
| `users`  | array of [codersdk.MCPServerConfigUser](#codersdkmcpserverconfiguser)   | false    |              |             |

## codersdk.MCPServerConfigGroup

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "role": "read",
  "source": "user",
  "total_member_count": 0
}
```

### Properties

| Name                        | Type                                                         | Required | Restrictions | Description                                                                                                                                                           |
|-----------------------------|--------------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `avatar_url`                | string                                                       | false    |              |                                                                                                                                                                       |
| `display_name`              | string                                                       | false    |              |                                                                                                                                                                       |
| `id`                        | string                                                       | false    |              |                                                                                                                                                                       |
| `members`                   | array of [codersdk.ReducedUser](#codersdkreduceduser)        | false    |              |                                                                                                                                                                       |
| `name`                      | string                                                       | false    |              |                                                                                                                                                                       |
| `organization_display_name` | string                                                       | false    |              |                                                                                                                                                                       |
| `organization_id`           | string                                                       | false    |              |                                                                                                                                                                       |
| `organization_name`         | string                                                       | false    |              |                                                                                                                                                                       |
| `quota_allowance`           | integer                                                      | false    |              |                                                                                                                                                                       |
| `role`                      | [codersdk.MCPServerConfigRole](#codersdkmcpserverconfigrole) | false    |              |                                                                                                                                                                       |
| `source`                    | [codersdk.GroupSource](#codersdkgroupsource)                 | false    |              |                                                                                                                                                                       |
| `total_member_count`        | integer                                                      | false    |              | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. |

#### Enumerated Values

| Property | Value(s) |
|----------|----------|
| `role`   | `read`   |

## codersdk.MCPServerConfigRole

```json
"read"
```

### Properties

#### Enumerated Values

| Value(s)   |
|------------|
| ``, `read` |

## codersdk.MCPServerConfigUser

```json
{
  "avatar_url": "http://example.com",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "role": "read",
  "username": "string"
}
```

### Properties

| Name         | Type                                                         | Required | Restrictions | Description |
|--------------|--------------------------------------------------------------|----------|--------------|-------------|
| `avatar_url` | string                                                       | false    |              |             |
| `id`         | string                                                       | true     |              |             |
| `name`       | string                                                       | false    |              |             |
| `role`       | [codersdk.MCPServerConfigRole](#codersdkmcpserverconfigrole) | false    |              |             |
| `username`   | string                                                       | true     |              |             |

#### Enumerated Values

| Property | Value(s) |
|----------|----------|
| `role`   | `read`   |

## codersdk.MCPServerOAuth2DisconnectResponse

```json
{
  "token_revocation_error": "string",
  "token_revoked": true
}
```

### Properties

| Name                     | Type    | Required | Restrictions | Description |
|--------------------------|---------|----------|--------------|-------------|
| `token_revocation_error` | string  | false    |              |             |
| `token_revoked`          | boolean | false    |              |             |

## codersdk.MatchedProvisioners

```json
{
  "available": 0,
  "count": 0,
  "most_recently_seen": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description                                                                                                                                                         |
|----------------------|---------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `available`          | integer | false    |              | Available is the number of provisioner daemons that are available to take jobs. This may be less than the count if some provisioners are busy or have been stopped. |
| `count`              | integer | false    |              | Count is the number of provisioner daemons that matched the given tags. If the count is 0, it means no provisioner daemons matched the requested tags.              |
| `most_recently_seen` | string  | false    |              | Most recently seen is the most recently seen time of the set of matched provisioners. If no provisioners matched, this field will be null.                          |

## codersdk.MinimalOrganization

```json
{
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `display_name` | string | false    |              |             |
| `icon`         | string | false    |              |             |
| `id`           | string | true     |              |             |
| `name`         | string | false    |              |             |

## codersdk.MinimalUser

```json
{
  "avatar_url": "http://example.com",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "username": "string"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description |
|--------------|--------|----------|--------------|-------------|
| `avatar_url` | string | false    |              |             |
| `id`         | string | true     |              |             |
| `name`       | string | false    |              |             |
| `username`   | string | true     |              |             |

## codersdk.NotificationMethodsResponse

```json
{
  "available": [
    "string"
  ],
  "default": "string"
}
```

### Properties

| Name        | Type            | Required | Restrictions | Description |
|-------------|-----------------|----------|--------------|-------------|
| `available` | array of string | false    |              |             |
| `default`   | string          | false    |              |             |

## codersdk.NotificationPreference

```json
{
  "disabled": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name         | Type    | Required | Restrictions | Description |
|--------------|---------|----------|--------------|-------------|
| `disabled`   | boolean | false    |              |             |
| `id`         | string  | false    |              |             |
| `updated_at` | string  | false    |              |             |

## codersdk.NotificationTemplate

```json
{
  "actions": "string",
  "body_template": "string",
  "enabled_by_default": true,
  "group": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "kind": "string",
  "method": "string",
  "name": "string",
  "title_template": "string"
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `actions`            | string  | false    |              |             |
| `body_template`      | string  | false    |              |             |
| `enabled_by_default` | boolean | false    |              |             |
| `group`              | string  | false    |              |             |
| `id`                 | string  | false    |              |             |
| `kind`               | string  | false    |              |             |
| `method`             | string  | false    |              |             |
| `name`               | string  | false    |              |             |
| `title_template`     | string  | false    |              |             |

## codersdk.NotificationsConfig

```json
{
  "dispatch_timeout": 0,
  "email": {
    "auth": {
      "identity": "string",
      "password": "string",
      "password_file": "string",
      "username": "string"
    },
    "force_tls": true,
    "from": "string",
    "hello": "string",
    "smarthost": "string",
    "tls": {
      "ca_file": "string",
      "cert_file": "string",
      "insecure_skip_verify": true,
      "key_file": "string",
      "server_name": "string",
      "start_tls": true
    }
  },
  "fetch_interval": 0,
  "inbox": {
    "enabled": true
  },
  "lease_count": 0,
  "lease_period": 0,
  "max_send_attempts": 0,
  "method": "string",
  "retry_interval": 0,
  "sync_buffer_size": 0,
  "sync_interval": 0,
  "webhook": {
    "endpoint": {
      "forceQuery": true,
      "fragment": "string",
      "host": "string",
      "omitHost": true,
      "opaque": "string",
      "path": "string",
      "rawFragment": "string",
      "rawPath": "string",
      "rawQuery": "string",
      "scheme": "string",
      "user": {}
    }
  }
}
```

### Properties

| Name                | Type                                                                       | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                                                                                                         |
|---------------------|----------------------------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `dispatch_timeout`  | integer                                                                    | false    |              | How long to wait while a notification is being sent before giving up.                                                                                                                                                                                                                                                                                                                                                                               |
| `email`             | [codersdk.NotificationsEmailConfig](#codersdknotificationsemailconfig)     | false    |              | Email settings.                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `fetch_interval`    | integer                                                                    | false    |              | How often to query the database for queued notifications.                                                                                                                                                                                                                                                                                                                                                                                           |
| `inbox`             | [codersdk.NotificationsInboxConfig](#codersdknotificationsinboxconfig)     | false    |              | Inbox settings.                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `lease_count`       | integer                                                                    | false    |              | How many notifications a notifier should lease per fetch interval.                                                                                                                                                                                                                                                                                                                                                                                  |
| `lease_period`      | integer                                                                    | false    |              | How long a notifier should lease a message. This is effectively how long a notification is 'owned' by a notifier, and once this period expires it will be available for lease by another notifier. Leasing is important in order for multiple running notifiers to not pick the same messages to deliver concurrently. This lease period will only expire if a notifier shuts down ungracefully; a dispatch of the notification releases the lease. |
| `max_send_attempts` | integer                                                                    | false    |              | The upper limit of attempts to send a notification.                                                                                                                                                                                                                                                                                                                                                                                                 |
| `method`            | string                                                                     | false    |              | Which delivery method to use (available options: 'smtp', 'webhook').                                                                                                                                                                                                                                                                                                                                                                                |
| `retry_interval`    | integer                                                                    | false    |              | The minimum time between retries.                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `sync_buffer_size`  | integer                                                                    | false    |              | The notifications system buffers message updates in memory to ease pressure on the database. This option controls how many updates are kept in memory. The lower this value the lower the change of state inconsistency in a non-graceful shutdown - but it also increases load on the database. It is recommended to keep this option at its default value.                                                                                        |
| `sync_interval`     | integer                                                                    | false    |              | The notifications system buffers message updates in memory to ease pressure on the database. This option controls how often it synchronizes its state with the database. The shorter this value the lower the change of state inconsistency in a non-graceful shutdown - but it also increases load on the database. It is recommended to keep this option at its default value.                                                                    |
| `webhook`           | [codersdk.NotificationsWebhookConfig](#codersdknotificationswebhookconfig) | false    |              | Webhook settings.                                                                                                                                                                                                                                                                                                                                                                                                                                   |

## codersdk.NotificationsEmailAuthConfig

```json
{
  "identity": "string",
  "password": "string",
  "password_file": "string",
  "username": "string"
}
```

### Properties

| Name            | Type   | Required | Restrictions | Description                                                |
|-----------------|--------|----------|--------------|------------------------------------------------------------|
| `identity`      | string | false    |              | Identity for PLAIN auth.                                   |
| `password`      | string | false    |              | Password for LOGIN/PLAIN auth.                             |
| `password_file` | string | false    |              | File from which to load the password for LOGIN/PLAIN auth. |
| `username`      | string | false    |              | Username for LOGIN/PLAIN auth.                             |

## codersdk.NotificationsEmailConfig

```json
{
  "auth": {
    "identity": "string",
    "password": "string",
    "password_file": "string",
    "username": "string"
  },
  "force_tls": true,
  "from": "string",
  "hello": "string",
  "smarthost": "string",
  "tls": {
    "ca_file": "string",
    "cert_file": "string",
    "insecure_skip_verify": true,
    "key_file": "string",
    "server_name": "string",
    "start_tls": true
  }
}
```

### Properties

| Name        | Type                                                                           | Required | Restrictions | Description                                                           |
|-------------|--------------------------------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------|
| `auth`      | [codersdk.NotificationsEmailAuthConfig](#codersdknotificationsemailauthconfig) | false    |              | Authentication details.                                               |
| `force_tls` | boolean                                                                        | false    |              | Force tls causes a TLS connection to be attempted.                    |
| `from`      | string                                                                         | false    |              | The sender's address.                                                 |
| `hello`     | string                                                                         | false    |              | The hostname identifying the SMTP server.                             |
| `smarthost` | string                                                                         | false    |              | The intermediary SMTP host through which emails are sent (host:port). |
| `tls`       | [codersdk.NotificationsEmailTLSConfig](#codersdknotificationsemailtlsconfig)   | false    |              | Tls details.                                                          |

## codersdk.NotificationsEmailTLSConfig

```json
{
  "ca_file": "string",
  "cert_file": "string",
  "insecure_skip_verify": true,
  "key_file": "string",
  "server_name": "string",
  "start_tls": true
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description                                                  |
|------------------------|---------|----------|--------------|--------------------------------------------------------------|
| `ca_file`              | string  | false    |              | Ca file specifies the location of the CA certificate to use. |
| `cert_file`            | string  | false    |              | Cert file specifies the location of the certificate to use.  |
| `insecure_skip_verify` | boolean | false    |              | Insecure skip verify skips target certificate validation.    |
| `key_file`             | string  | false    |              | Key file specifies the location of the key to use.           |
| `server_name`          | string  | false    |              | Server name to verify the hostname for the targets.          |
| `start_tls`            | boolean | false    |              | Start tls attempts to upgrade plain connections to TLS.      |

## codersdk.NotificationsInboxConfig

```json
{
  "enabled": true
}
```

### Properties

| Name      | Type    | Required | Restrictions | Description |
|-----------|---------|----------|--------------|-------------|
| `enabled` | boolean | false    |              |             |

## codersdk.NotificationsSettings

```json
{
  "notifier_paused": true
}
```

### Properties

| Name              | Type    | Required | Restrictions | Description |
|-------------------|---------|----------|--------------|-------------|
| `notifier_paused` | boolean | false    |              |             |

## codersdk.NotificationsWebhookConfig

```json
{
  "endpoint": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  }
}
```

### Properties

| Name       | Type                       | Required | Restrictions | Description                                                          |
|------------|----------------------------|----------|--------------|----------------------------------------------------------------------|
| `endpoint` | [serpent.URL](#serpenturl) | false    |              | The URL to which the payload will be sent with an HTTP POST request. |

## codersdk.NullHCLString

```json
{
  "valid": true,
  "value": "string"
}
```

### Properties

| Name    | Type    | Required | Restrictions | Description |
|---------|---------|----------|--------------|-------------|
| `valid` | boolean | false    |              |             |
| `value` | string  | false    |              |             |

## codersdk.OAuth2AppEndpoints

```json
{
  "authorization": "string",
  "device_authorization": "string",
  "token": "string",
  "token_revoke": "string"
}
```

### Properties

| Name                   | Type   | Required | Restrictions | Description                       |
|------------------------|--------|----------|--------------|-----------------------------------|
| `authorization`        | string | false    |              |                                   |
| `device_authorization` | string | false    |              | Device authorization is optional. |
| `token`                | string | false    |              |                                   |
| `token_revoke`         | string | false    |              |                                   |

## codersdk.OAuth2AuthorizationServerMetadata

```json
{
  "authorization_endpoint": "string",
  "code_challenge_methods_supported": [
    "S256"
  ],
  "grant_types_supported": [
    "authorization_code"
  ],
  "issuer": "string",
  "registration_endpoint": "string",
  "response_types_supported": [
    "code"
  ],
  "revocation_endpoint": "string",
  "scopes_supported": [
    "string"
  ],
  "token_endpoint": "string",
  "token_endpoint_auth_methods_supported": [
    "client_secret_basic"
  ]
}
```

### Properties

| Name                                    | Type                                                                                      | Required | Restrictions | Description |
|-----------------------------------------|-------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `authorization_endpoint`                | string                                                                                    | false    |              |             |
| `code_challenge_methods_supported`      | array of [codersdk.OAuth2PKCECodeChallengeMethod](#codersdkoauth2pkcecodechallengemethod) | false    |              |             |
| `grant_types_supported`                 | array of [codersdk.OAuth2ProviderGrantType](#codersdkoauth2providergranttype)             | false    |              |             |
| `issuer`                                | string                                                                                    | false    |              |             |
| `registration_endpoint`                 | string                                                                                    | false    |              |             |
| `response_types_supported`              | array of [codersdk.OAuth2ProviderResponseType](#codersdkoauth2providerresponsetype)       | false    |              |             |
| `revocation_endpoint`                   | string                                                                                    | false    |              |             |
| `scopes_supported`                      | array of string                                                                           | false    |              |             |
| `token_endpoint`                        | string                                                                                    | false    |              |             |
| `token_endpoint_auth_methods_supported` | array of [codersdk.OAuth2TokenEndpointAuthMethod](#codersdkoauth2tokenendpointauthmethod) | false    |              |             |

## codersdk.OAuth2ClientConfiguration

```json
{
  "client_id": "string",
  "client_id_issued_at": 0,
  "client_name": "string",
  "client_secret_expires_at": 0,
  "client_uri": "string",
  "contacts": [
    "string"
  ],
  "grant_types": [
    "authorization_code"
  ],
  "jwks": {},
  "jwks_uri": "string",
  "logo_uri": "string",
  "policy_uri": "string",
  "redirect_uris": [
    "string"
  ],
  "registration_access_token": "string",
  "registration_client_uri": "string",
  "response_types": [
    "code"
  ],
  "scope": "string",
  "software_id": "string",
  "software_version": "string",
  "token_endpoint_auth_method": "client_secret_basic",
  "tos_uri": "string"
}
```

### Properties

| Name                         | Type                                                                                | Required | Restrictions | Description |
|------------------------------|-------------------------------------------------------------------------------------|----------|--------------|-------------|
| `client_id`                  | string                                                                              | false    |              |             |
| `client_id_issued_at`        | integer                                                                             | false    |              |             |
| `client_name`                | string                                                                              | false    |              |             |
| `client_secret_expires_at`   | integer                                                                             | false    |              |             |
| `client_uri`                 | string                                                                              | false    |              |             |
| `contacts`                   | array of string                                                                     | false    |              |             |
| `grant_types`                | array of [codersdk.OAuth2ProviderGrantType](#codersdkoauth2providergranttype)       | false    |              |             |
| `jwks`                       | object                                                                              | false    |              |             |
| `jwks_uri`                   | string                                                                              | false    |              |             |
| `logo_uri`                   | string                                                                              | false    |              |             |
| `policy_uri`                 | string                                                                              | false    |              |             |
| `redirect_uris`              | array of string                                                                     | false    |              |             |
| `registration_access_token`  | string                                                                              | false    |              |             |
| `registration_client_uri`    | string                                                                              | false    |              |             |
| `response_types`             | array of [codersdk.OAuth2ProviderResponseType](#codersdkoauth2providerresponsetype) | false    |              |             |
| `scope`                      | string                                                                              | false    |              |             |
| `software_id`                | string                                                                              | false    |              |             |
| `software_version`           | string                                                                              | false    |              |             |
| `token_endpoint_auth_method` | [codersdk.OAuth2TokenEndpointAuthMethod](#codersdkoauth2tokenendpointauthmethod)    | false    |              |             |
| `tos_uri`                    | string                                                                              | false    |              |             |

## codersdk.OAuth2ClientRegistrationRequest

```json
{
  "client_name": "string",
  "client_uri": "string",
  "contacts": [
    "string"
  ],
  "grant_types": [
    "authorization_code"
  ],
  "jwks": {},
  "jwks_uri": "string",
  "logo_uri": "string",
  "policy_uri": "string",
  "redirect_uris": [
    "string"
  ],
  "response_types": [
    "code"
  ],
  "scope": "string",
  "software_id": "string",
  "software_statement": "string",
  "software_version": "string",
  "token_endpoint_auth_method": "client_secret_basic",
  "tos_uri": "string"
}
```

### Properties

| Name                         | Type                                                                                | Required | Restrictions | Description |
|------------------------------|-------------------------------------------------------------------------------------|----------|--------------|-------------|
| `client_name`                | string                                                                              | false    |              |             |
| `client_uri`                 | string                                                                              | false    |              |             |
| `contacts`                   | array of string                                                                     | false    |              |             |
| `grant_types`                | array of [codersdk.OAuth2ProviderGrantType](#codersdkoauth2providergranttype)       | false    |              |             |
| `jwks`                       | object                                                                              | false    |              |             |
| `jwks_uri`                   | string                                                                              | false    |              |             |
| `logo_uri`                   | string                                                                              | false    |              |             |
| `policy_uri`                 | string                                                                              | false    |              |             |
| `redirect_uris`              | array of string                                                                     | false    |              |             |
| `response_types`             | array of [codersdk.OAuth2ProviderResponseType](#codersdkoauth2providerresponsetype) | false    |              |             |
| `scope`                      | string                                                                              | false    |              |             |
| `software_id`                | string                                                                              | false    |              |             |
| `software_statement`         | string                                                                              | false    |              |             |
| `software_version`           | string                                                                              | false    |              |             |
| `token_endpoint_auth_method` | [codersdk.OAuth2TokenEndpointAuthMethod](#codersdkoauth2tokenendpointauthmethod)    | false    |              |             |
| `tos_uri`                    | string                                                                              | false    |              |             |

## codersdk.OAuth2ClientRegistrationResponse

```json
{
  "client_id": "string",
  "client_id_issued_at": 0,
  "client_name": "string",
  "client_secret": "string",
  "client_secret_expires_at": 0,
  "client_uri": "string",
  "contacts": [
    "string"
  ],
  "grant_types": [
    "authorization_code"
  ],
  "jwks": {},
  "jwks_uri": "string",
  "logo_uri": "string",
  "policy_uri": "string",
  "redirect_uris": [
    "string"
  ],
  "registration_access_token": "string",
  "registration_client_uri": "string",
  "response_types": [
    "code"
  ],
  "scope": "string",
  "software_id": "string",
  "software_version": "string",
  "token_endpoint_auth_method": "client_secret_basic",
  "tos_uri": "string"
}
```

### Properties

| Name                         | Type                                                                                | Required | Restrictions | Description |
|------------------------------|-------------------------------------------------------------------------------------|----------|--------------|-------------|
| `client_id`                  | string                                                                              | false    |              |             |
| `client_id_issued_at`        | integer                                                                             | false    |              |             |
| `client_name`                | string                                                                              | false    |              |             |
| `client_secret`              | string                                                                              | false    |              |             |
| `client_secret_expires_at`   | integer                                                                             | false    |              |             |
| `client_uri`                 | string                                                                              | false    |              |             |
| `contacts`                   | array of string                                                                     | false    |              |             |
| `grant_types`                | array of [codersdk.OAuth2ProviderGrantType](#codersdkoauth2providergranttype)       | false    |              |             |
| `jwks`                       | object                                                                              | false    |              |             |
| `jwks_uri`                   | string                                                                              | false    |              |             |
| `logo_uri`                   | string                                                                              | false    |              |             |
| `policy_uri`                 | string                                                                              | false    |              |             |
| `redirect_uris`              | array of string                                                                     | false    |              |             |
| `registration_access_token`  | string                                                                              | false    |              |             |
| `registration_client_uri`    | string                                                                              | false    |              |             |
| `response_types`             | array of [codersdk.OAuth2ProviderResponseType](#codersdkoauth2providerresponsetype) | false    |              |             |
| `scope`                      | string                                                                              | false    |              |             |
| `software_id`                | string                                                                              | false    |              |             |
| `software_version`           | string                                                                              | false    |              |             |
| `token_endpoint_auth_method` | [codersdk.OAuth2TokenEndpointAuthMethod](#codersdkoauth2tokenendpointauthmethod)    | false    |              |             |
| `tos_uri`                    | string                                                                              | false    |              |             |

## codersdk.OAuth2ClientType

```json
"confidential"
```

### Properties

#### Enumerated Values

| Value(s)                 |
|--------------------------|
| `confidential`, `public` |

## codersdk.OAuth2Config

```json
{
  "github": {
    "allow_everyone": true,
    "allow_signups": true,
    "allowed_orgs": [
      "string"
    ],
    "allowed_teams": [
      "string"
    ],
    "client_id": "string",
    "client_secret": "string",
    "default_provider_enable": true,
    "device_flow": true,
    "enterprise_base_url": "string"
  },
  "provider": {
    "enable": true
  }
}
```

### Properties

| Name       | Type                                                           | Required | Restrictions | Description |
|------------|----------------------------------------------------------------|----------|--------------|-------------|
| `github`   | [codersdk.OAuth2GithubConfig](#codersdkoauth2githubconfig)     | false    |              |             |
| `provider` | [codersdk.OAuth2ProviderConfig](#codersdkoauth2providerconfig) | false    |              |             |

## codersdk.OAuth2Error

```json
{
  "error": "invalid_request",
  "error_description": "string",
  "error_uri": "string"
}
```

### Properties

| Name                | Type                                                 | Required | Restrictions | Description |
|---------------------|------------------------------------------------------|----------|--------------|-------------|
| `error`             | [codersdk.OAuth2ErrorCode](#codersdkoauth2errorcode) | false    |              |             |
| `error_description` | string                                               | false    |              |             |
| `error_uri`         | string                                               | false    |              |             |

## codersdk.OAuth2ErrorCode

```json
"invalid_request"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                                                                                                    |
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `access_denied`, `invalid_client`, `invalid_grant`, `invalid_request`, `invalid_scope`, `invalid_target`, `server_error`, `temporarily_unavailable`, `unauthorized_client`, `unsupported_grant_type`, `unsupported_response_type`, `unsupported_token_type` |

## codersdk.OAuth2GithubConfig

```json
{
  "allow_everyone": true,
  "allow_signups": true,
  "allowed_orgs": [
    "string"
  ],
  "allowed_teams": [
    "string"
  ],
  "client_id": "string",
  "client_secret": "string",
  "default_provider_enable": true,
  "device_flow": true,
  "enterprise_base_url": "string"
}
```

### Properties

| Name                      | Type            | Required | Restrictions | Description |
|---------------------------|-----------------|----------|--------------|-------------|
| `allow_everyone`          | boolean         | false    |              |             |
| `allow_signups`           | boolean         | false    |              |             |
| `allowed_orgs`            | array of string | false    |              |             |
| `allowed_teams`           | array of string | false    |              |             |
| `client_id`               | string          | false    |              |             |
| `client_secret`           | string          | false    |              |             |
| `default_provider_enable` | boolean         | false    |              |             |
| `device_flow`             | boolean         | false    |              |             |
| `enterprise_base_url`     | string          | false    |              |             |

## codersdk.OAuth2PKCECodeChallengeMethod

```json
"S256"
```

### Properties

#### Enumerated Values

| Value(s)        |
|-----------------|
| `S256`, `plain` |

## codersdk.OAuth2ProtectedResourceMetadata

```json
{
  "authorization_servers": [
    "string"
  ],
  "bearer_methods_supported": [
    "string"
  ],
  "resource": "string",
  "scopes_supported": [
    "string"
  ]
}
```

### Properties

| Name                       | Type            | Required | Restrictions | Description |
|----------------------------|-----------------|----------|--------------|-------------|
| `authorization_servers`    | array of string | false    |              |             |
| `bearer_methods_supported` | array of string | false    |              |             |
| `resource`                 | string          | false    |              |             |
| `scopes_supported`         | array of string | false    |              |             |

## codersdk.OAuth2ProviderApp

```json
{
  "callback_url": "string",
  "client_type": "confidential",
  "dynamically_registered": true,
  "endpoints": {
    "authorization": "string",
    "device_authorization": "string",
    "token": "string",
    "token_revoke": "string"
  },
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "redirect_uris": [
    "string"
  ],
  "scope": "string"
}
```

### Properties

| Name                     | Type                                                       | Required | Restrictions | Description                                                                                                                                                                                             |
|--------------------------|------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `callback_url`           | string                                                     | false    |              | Deprecated: equal to the first entry of redirect_uris. Read redirect_uris instead.                                                                                                                      |
| `client_type`            | [codersdk.OAuth2ClientType](#codersdkoauth2clienttype)     | false    |              | Client type is "confidential" or "public".                                                                                                                                                              |
| `dynamically_registered` | boolean                                                    | false    |              | Dynamically registered is true when the app registered itself through Dynamic Client Registration rather than being created by an admin.                                                                |
| `endpoints`              | [codersdk.OAuth2AppEndpoints](#codersdkoauth2appendpoints) | false    |              | Endpoints are included in the app response for easier discovery. The OAuth2 spec does not have a defined place to find these (for comparison, OIDC has a '/.well-known/openid-configuration' endpoint). |
| `icon`                   | string                                                     | false    |              |                                                                                                                                                                                                         |
| `id`                     | string                                                     | false    |              |                                                                                                                                                                                                         |
| `name`                   | string                                                     | false    |              |                                                                                                                                                                                                         |
| `redirect_uris`          | array of string                                            | false    |              | Redirect uris are the app's registered redirect URIs, primary first.                                                                                                                                    |
| `scope`                  | string                                                     | false    |              | Scope is the space-separated list of scopes this app's tokens may be granted. Empty means unrestricted. A non-empty value with no names is a configured allowlist that grants nothing.                  |

## codersdk.OAuth2ProviderAppSecret

```json
{
  "client_secret_truncated": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "last_used_at": "string"
}
```

### Properties

| Name                      | Type   | Required | Restrictions | Description |
|---------------------------|--------|----------|--------------|-------------|
| `client_secret_truncated` | string | false    |              |             |
| `id`                      | string | false    |              |             |
| `last_used_at`            | string | false    |              |             |

## codersdk.OAuth2ProviderAppSecretFull

```json
{
  "client_secret_full": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}
```

### Properties

| Name                 | Type   | Required | Restrictions | Description |
|----------------------|--------|----------|--------------|-------------|
| `client_secret_full` | string | false    |              |             |
| `id`                 | string | false    |              |             |

## codersdk.OAuth2ProviderConfig

```json
{
  "enable": true
}
```

### Properties

| Name     | Type    | Required | Restrictions | Description |
|----------|---------|----------|--------------|-------------|
| `enable` | boolean | false    |              |             |

## codersdk.OAuth2ProviderGrantType

```json
"authorization_code"
```

### Properties

#### Enumerated Values

| Value(s)                                                                            |
|-------------------------------------------------------------------------------------|
| `authorization_code`, `client_credentials`, `implicit`, `password`, `refresh_token` |

## codersdk.OAuth2ProviderResponseType

```json
"code"
```

### Properties

#### Enumerated Values

| Value(s)        |
|-----------------|
| `code`, `token` |

## codersdk.OAuth2ProviderSettings

```json
{
  "dynamic_client_registration_enabled": true
}
```

### Properties

| Name                                  | Type    | Required | Restrictions | Description |
|---------------------------------------|---------|----------|--------------|-------------|
| `dynamic_client_registration_enabled` | boolean | false    |              |             |

## codersdk.OAuth2TokenEndpointAuthMethod

```json
"client_secret_basic"
```

### Properties

#### Enumerated Values

| Value(s)                                            |
|-----------------------------------------------------|
| `client_secret_basic`, `client_secret_post`, `none` |

## codersdk.OAuth2TokenResponse

```json
{
  "access_token": "string",
  "expires_in": 0,
  "expiry": "2019-08-24T14:15:22Z",
  "refresh_token": "string",
  "scope": "string",
  "token_type": "Bearer"
}
```

### Properties

| Name            | Type                                                 | Required | Restrictions | Description                                                                                                                          |
|-----------------|------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------|
| `access_token`  | string                                               | false    |              |                                                                                                                                      |
| `expires_in`    | integer                                              | false    |              |                                                                                                                                      |
| `expiry`        | string                                               | false    |              | Expiry is not part of RFC 6749 but is included for compatibility with golang.org/x/oauth2.Token and clients that expect a timestamp. |
| `refresh_token` | string                                               | false    |              |                                                                                                                                      |
| `scope`         | string                                               | false    |              |                                                                                                                                      |
| `token_type`    | [codersdk.OAuth2TokenType](#codersdkoauth2tokentype) | false    |              |                                                                                                                                      |

## codersdk.OAuth2TokenType

```json
"Bearer"
```

### Properties

#### Enumerated Values

| Value(s)         |
|------------------|
| `Bearer`, `DPoP` |

## codersdk.OAuthConversionResponse

```json
{
  "expires_at": "2019-08-24T14:15:22Z",
  "state_string": "string",
  "to_type": "",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name           | Type                                     | Required | Restrictions | Description |
|----------------|------------------------------------------|----------|--------------|-------------|
| `expires_at`   | string                                   | false    |              |             |
| `state_string` | string                                   | false    |              |             |
| `to_type`      | [codersdk.LoginType](#codersdklogintype) | false    |              |             |
| `user_id`      | string                                   | false    |              |             |

## codersdk.OIDCAuthMethod

```json
{
  "enabled": true,
  "iconUrl": "string",
  "signInText": "string"
}
```

### Properties

| Name         | Type    | Required | Restrictions | Description |
|--------------|---------|----------|--------------|-------------|
| `enabled`    | boolean | false    |              |             |
| `iconUrl`    | string  | false    |              |             |
| `signInText` | string  | false    |              |             |

## codersdk.OIDCClaimsResponse

```json
{
  "claims": {}
}
```

### Properties

| Name     | Type   | Required | Restrictions | Description                                                                                                                                                                 |
|----------|--------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `claims` | object | false    |              | Claims are the merged claims from the OIDC provider. These are the union of the ID token claims and the userinfo claims, where userinfo claims take precedence on conflict. |

## codersdk.OIDCConfig

```json
{
  "allow_signups": true,
  "auth_url_params": {},
  "auto_repair_links": true,
  "client_cert_file": "string",
  "client_id": "string",
  "client_key_file": "string",
  "client_secret": "string",
  "email_domain": [
    "string"
  ],
  "email_fallback": true,
  "email_field": "string",
  "group_allow_list": [
    "string"
  ],
  "group_auto_create": true,
  "group_mapping": {},
  "group_regex_filter": {},
  "groups_field": "string",
  "icon_url": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  },
  "ignore_email_verified": true,
  "ignore_user_info": true,
  "issuer_url": "string",
  "name_field": "string",
  "organization_assign_default": true,
  "organization_field": "string",
  "organization_mapping": {},
  "redirect_allowed_hosts": [
    "string"
  ],
  "redirect_url": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  },
  "scopes": [
    "string"
  ],
  "sign_in_text": "string",
  "signups_disabled_text": "string",
  "skip_issuer_checks": true,
  "source_user_info_from_access_token": true,
  "user_role_field": "string",
  "user_role_mapping": {},
  "user_roles_default": [
    "string"
  ],
  "username_field": "string"
}
```

### Properties

| Name                                 | Type                             | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                |
|--------------------------------------|----------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `allow_signups`                      | boolean                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `auth_url_params`                    | object                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `auto_repair_links`                  | boolean                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `client_cert_file`                   | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `client_id`                          | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `client_key_file`                    | string                           | false    |              | Client key file & ClientCertFile are used in place of ClientSecret for PKI auth.                                                                                                                                                                                                                                                                                                                                                                           |
| `client_secret`                      | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `email_domain`                       | array of string                  | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `email_fallback`                     | boolean                          | false    |              | Email fallback allows OIDC logins to fall back to email-based matching when the `linked_id` (issuer+subject) does not match an existing user link. INSECURE: weakens the linked_id check. It exists for IdP brokers that do not issue a stable `sub` for the same user across connections.                                                                                                                                                                 |
| `email_field`                        | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `group_allow_list`                   | array of string                  | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `group_auto_create`                  | boolean                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `group_mapping`                      | object                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `group_regex_filter`                 | [serpent.Regexp](#serpentregexp) | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `groups_field`                       | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `icon_url`                           | [serpent.URL](#serpenturl)       | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `ignore_email_verified`              | boolean                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `ignore_user_info`                   | boolean                          | false    |              | Ignore user info & UserInfoFromAccessToken are mutually exclusive. Only 1 can be set to true. Ideally this would be an enum with 3 states, ['none', 'userinfo', 'access_token']. However, for backward compatibility, `ignore_user_info` must remain. And `access_token` is a niche, non-spec compliant edge case. So it's use is rare, and should not be advised.                                                                                         |
| `issuer_url`                         | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `name_field`                         | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `organization_assign_default`        | boolean                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `organization_field`                 | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `organization_mapping`               | object                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `redirect_allowed_hosts`             | array of string                  | false    |              | Redirect allowed hosts is an allowlist of hostnames that may be used as the host of the OIDC redirect_uri. When non-empty, the redirect_uri is constructed from the incoming request's Host header (validated against this list) instead of from AccessURL. Every listed host must also be registered as a valid redirect URI in the OIDC provider. This setting is mutually exclusive with RedirectURL: if RedirectURL is set, this allowlist is ignored. |
| `redirect_url`                       | [serpent.URL](#serpenturl)       | false    |              | Redirect URL is optional, defaulting to 'ACCESS_URL'. Only useful in niche situations where the OIDC callback domain is different from the ACCESS_URL domain. The path component is ignored.                                                                                                                                                                                                                                                               |
| `scopes`                             | array of string                  | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `sign_in_text`                       | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `signups_disabled_text`              | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `skip_issuer_checks`                 | boolean                          | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `source_user_info_from_access_token` | boolean                          | false    |              | Source user info from access token as mentioned above is an edge case. This allows sourcing the user_info from the access token itself instead of a user_info endpoint. This assumes the access token is a valid JWT with a set of claims to be merged with the id_token.                                                                                                                                                                                  |
| `user_role_field`                    | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `user_role_mapping`                  | object                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `user_roles_default`                 | array of string                  | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `username_field`                     | string                           | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                                            |

## codersdk.OptionType

```json
"string"
```

### Properties

#### Enumerated Values

| Value(s)                                   |
|--------------------------------------------|
| `bool`, `list(string)`, `number`, `string` |

## codersdk.Organization

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "default_org_member_roles": [
    "string"
  ],
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_default": true,
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name                       | Type            | Required | Restrictions | Description                                                                                                                                     |
|----------------------------|-----------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| `created_at`               | string          | true     |              |                                                                                                                                                 |
| `default_org_member_roles` | array of string | false    |              | Default org member roles are unioned into every member's effective roles at request time. Changes propagate to all members on the next request. |
| `description`              | string          | false    |              |                                                                                                                                                 |
| `display_name`             | string          | false    |              |                                                                                                                                                 |
| `icon`                     | string          | false    |              |                                                                                                                                                 |
| `id`                       | string          | true     |              |                                                                                                                                                 |
| `is_default`               | boolean         | true     |              |                                                                                                                                                 |
| `name`                     | string          | false    |              |                                                                                                                                                 |
| `updated_at`               | string          | true     |              |                                                                                                                                                 |

## codersdk.OrganizationAISpendReport

```json
{
  "count": 0,
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z",
  "retention_start": "2019-08-24T14:15:22Z",
  "totals": {
    "cost_micros": 0,
    "unpriced_usage_count": 0
  },
  "users": [
    {
      "avatar_url": "string",
      "clients": [
        "string"
      ],
      "cost_micros": 0,
      "models": [
        "string"
      ],
      "name": "string",
      "providers": [
        "string"
      ],
      "unpriced_usage_count": 0,
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
      "username": "string"
    }
  ]
}
```

### Properties

| Name              | Type                                                                          | Required | Restrictions | Description                                                                                                                                                                             |
|-------------------|-------------------------------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `count`           | integer                                                                       | false    |              | Count is the number of users with token usage matching the filter.                                                                                                                      |
| `period_end`      | string                                                                        | false    |              | Period end is the exclusive upper bound of the current budget period.                                                                                                                   |
| `period_start`    | string                                                                        | false    |              | Period start is the inclusive lower bound of the current budget period.                                                                                                                 |
| `retention_start` | string                                                                        | false    |              | Retention start is the oldest instant for which token usage is still retained. An explicit period must not start before it. Omitted when the deployment does not purge AI Gateway data. |
| `totals`          | [codersdk.OrganizationAISpendTotals](#codersdkorganizationaispendtotals)      | false    |              |                                                                                                                                                                                         |
| `users`           | array of [codersdk.OrganizationAISpendUser](#codersdkorganizationaispenduser) | false    |              | Users is the requested page, most expensive first.                                                                                                                                      |

## codersdk.OrganizationAISpendTotals

```json
{
  "cost_micros": 0,
  "unpriced_usage_count": 0
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description                                                                                          |
|------------------------|---------|----------|--------------|------------------------------------------------------------------------------------------------------|
| `cost_micros`          | integer | false    |              | Cost micros is the priced spend of every matching user.                                              |
| `unpriced_usage_count` | integer | false    |              | Unpriced usage count is the number of token usage records without a cost across every matching user. |

## codersdk.OrganizationAISpendUser

```json
{
  "avatar_url": "string",
  "clients": [
    "string"
  ],
  "cost_micros": 0,
  "models": [
    "string"
  ],
  "name": "string",
  "providers": [
    "string"
  ],
  "unpriced_usage_count": 0,
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  "username": "string"
}
```

### Properties

| Name                   | Type            | Required | Restrictions | Description                                                                                                                                       |
|------------------------|-----------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------|
| `avatar_url`           | string          | false    |              |                                                                                                                                                   |
| `clients`              | array of string | false    |              | Clients are the clients the user spent through, sorted. Usage without a recorded client is reported as Unknown.                                   |
| `cost_micros`          | integer         | false    |              | Cost micros is the user's priced spend over the period.                                                                                           |
| `models`               | array of string | false    |              | Models are the models the user spent through, sorted.                                                                                             |
| `name`                 | string          | false    |              |                                                                                                                                                   |
| `providers`            | array of string | false    |              | Providers are the provider types the user spent through, sorted.                                                                                  |
| `unpriced_usage_count` | integer         | false    |              | Unpriced usage count is the number of the user's token usage records that carry no cost because their model had no price when they were recorded. |
| `user_id`              | string          | false    |              |                                                                                                                                                   |
| `username`             | string          | false    |              |                                                                                                                                                   |

## codersdk.OrganizationChatModelsResponse

```json
{
  "models": [
    {
      "ai_provider_id": "5a3b8ff9-20e7-4c37-ba1a-5b433e355819",
      "compression_threshold": 0,
      "context_limit": 0,
      "created_at": "2019-08-24T14:15:22Z",
      "display_name": "string",
      "enabled": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_default": true,
      "model": "string",
      "model_config": {
        "frequency_penalty": 0,
        "max_output_tokens": 0,
        "openai_config": {
          "reasoning_model": true,
          "use_responses_api": true
        },
        "presence_penalty": 0,
        "provider_options": {
          "anthropic": {
            "allowed_domains": [
              "string"
            ],
            "blocked_domains": [
              "string"
            ],
            "context_1m_enabled": true,
            "disable_parallel_tool_use": true,
            "send_reasoning": true,
            "thinking": {
              "budget_tokens": 0
            },
            "thinking_display": "string",
            "web_search_enabled": true
          },
          "google": {
            "cached_content": "string",
            "safety_settings": [
              {
                "category": "string",
                "threshold": "string"
              }
            ],
            "thinking_config": {
              "include_thoughts": true,
              "thinking_budget": 0,
              "thinking_level": "string"
            },
            "threshold": "string",
            "web_search_enabled": true
          },
          "openai": {
            "allowed_domains": [
              "string"
            ],
            "include": [
              "string"
            ],
            "instructions": "string",
            "log_probs": true,
            "logit_bias": {
              "property1": 0,
              "property2": 0
            },
            "max_completion_tokens": 0,
            "max_tool_calls": 0,
            "metadata": {
              "property1": null,
              "property2": null
            },
            "parallel_tool_calls": true,
            "prediction": {
              "property1": null,
              "property2": null
            },
            "prompt_cache_key": "string",
            "reasoning_mode": "string",
            "reasoning_summary": "string",
            "safety_identifier": "string",
            "search_context_size": "string",
            "service_tier": "string",
            "store": true,
            "strict_json_schema": true,
            "structured_outputs": true,
            "text_verbosity": "string",
            "top_log_probs": 0,
            "user": "string",
            "web_search_enabled": true
          },
          "openaicompat": {
            "user": "string"
          },
          "openrouter": {
            "extra_body": {
              "property1": null,
              "property2": null
            },
            "include_usage": true,
            "log_probs": true,
            "logit_bias": {
              "property1": 0,
              "property2": 0
            },
            "parallel_tool_calls": true,
            "provider": {
              "allow_fallbacks": true,
              "data_collection": "string",
              "ignore": [
                "string"
              ],
              "only": [
                "string"
              ],
              "order": [
                "string"
              ],
              "quantizations": [
                "string"
              ],
              "require_parameters": true,
              "sort": "string"
            },
            "reasoning": {
              "enabled": true,
              "exclude": true,
              "max_tokens": 0
            },
            "user": "string"
          },
          "vercel": {
            "extra_body": {
              "property1": null,
              "property2": null
            },
            "logit_bias": {
              "property1": 0,
              "property2": 0
            },
            "logprobs": true,
            "parallel_tool_calls": true,
            "providerOptions": {
              "models": [
                "string"
              ],
              "order": [
                "string"
              ]
            },
            "reasoning": {
              "enabled": true,
              "exclude": true,
              "max_tokens": 0
            },
            "top_logprobs": 0,
            "user": "string"
          }
        },
        "reasoning_effort": {
          "default": "string",
          "max": "string"
        },
        "temperature": 0,
        "top_k": 0,
        "top_p": 0
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "reasoning_efforts": [
        "string"
      ],
      "updated_at": "2019-08-24T14:15:22Z"
    }
  ],
  "providers": [
    {
      "allow_user_api_key": true,
      "available": true,
      "display_name": "string",
      "enabled": true,
      "has_api_key": true,
      "has_effective_api_key": true,
      "has_user_api_key": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "type": "string",
      "unavailable_reason": "missing_api_key"
    }
  ],
  "unsupported_providers": [
    {
      "display_name": "string",
      "provider": "string"
    }
  ]
}
```

### Properties

| Name                    | Type                                                                                  | Required | Restrictions | Description |
|-------------------------|---------------------------------------------------------------------------------------|----------|--------------|-------------|
| `models`                | array of [codersdk.ChatModel](#codersdkchatmodel)                                     | false    |              |             |
| `providers`             | array of [codersdk.ChatModelProviderDescriptor](#codersdkchatmodelproviderdescriptor) | false    |              |             |
| `unsupported_providers` | array of [codersdk.ChatUnsupportedProvider](#codersdkchatunsupportedprovider)         | false    |              |             |

## codersdk.OrganizationGroupAISpend

```json
{
  "current_spend_micros": 0,
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0,
  "total_spend_limit_micros": 0
}
```

### Properties

| Name                       | Type    | Required | Restrictions | Description                                                                                                                                                                                                                                        |
|----------------------------|---------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `current_spend_micros`     | integer | false    |              | Current spend micros is the group's spend over the current budget period.                                                                                                                                                                          |
| `group_id`                 | string  | false    |              |                                                                                                                                                                                                                                                    |
| `spend_limit_micros`       | integer | false    |              | Spend limit micros is the group's configured AI spend budget per member. Null when the group has no configured budget.                                                                                                                             |
| `total_spend_limit_micros` | integer | false    |              | Total spend limit micros is the currently configured combined budget of the members attributed to this group, with each member's override replacing their share. Null when the group has no budget, and zero when no members are attributed to it. |

## codersdk.OrganizationGroupsAISpend

```json
{
  "groups": [
    {
      "current_spend_micros": 0,
      "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
      "spend_limit_micros": 0,
      "total_spend_limit_micros": 0
    }
  ],
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name           | Type                                                                            | Required | Restrictions | Description                                                             |
|----------------|---------------------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------|
| `groups`       | array of [codersdk.OrganizationGroupAISpend](#codersdkorganizationgroupaispend) | false    |              |                                                                         |
| `period_end`   | string                                                                          | false    |              | Period end is the exclusive upper bound of the current budget period.   |
| `period_start` | string                                                                          | false    |              | Period start is the inclusive lower bound of the current budget period. |

## codersdk.OrganizationMember

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name              | Type                                            | Required | Restrictions | Description |
|-------------------|-------------------------------------------------|----------|--------------|-------------|
| `created_at`      | string                                          | false    |              |             |
| `organization_id` | string                                          | false    |              |             |
| `roles`           | array of [codersdk.SlimRole](#codersdkslimrole) | false    |              |             |
| `updated_at`      | string                                          | false    |              |             |
| `user_id`         | string                                          | false    |              |             |

## codersdk.OrganizationMemberWithUserData

```json
{
  "avatar_url": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "string",
  "global_roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "has_ai_seat": true,
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "updated_at": "2019-08-24T14:15:22Z",
  "user_created_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  "user_updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Properties

| Name                 | Type                                            | Required | Restrictions | Description                                                                                      |
|----------------------|-------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------|
| `avatar_url`         | string                                          | false    |              |                                                                                                  |
| `created_at`         | string                                          | false    |              |                                                                                                  |
| `email`              | string                                          | false    |              |                                                                                                  |
| `global_roles`       | array of [codersdk.SlimRole](#codersdkslimrole) | false    |              |                                                                                                  |
| `has_ai_seat`        | boolean                                         | false    |              | Has ai seat intentionally omits omitempty so the API always includes the field, even when false. |
| `is_service_account` | boolean                                         | false    |              |                                                                                                  |
| `last_seen_at`       | string                                          | false    |              |                                                                                                  |
| `login_type`         | [codersdk.LoginType](#codersdklogintype)        | false    |              |                                                                                                  |
| `name`               | string                                          | false    |              |                                                                                                  |
| `organization_id`    | string                                          | false    |              |                                                                                                  |
| `roles`              | array of [codersdk.SlimRole](#codersdkslimrole) | false    |              |                                                                                                  |
| `status`             | [codersdk.UserStatus](#codersdkuserstatus)      | false    |              |                                                                                                  |
| `updated_at`         | string                                          | false    |              |                                                                                                  |
| `user_created_at`    | string                                          | false    |              |                                                                                                  |
| `user_id`            | string                                          | false    |              |                                                                                                  |
| `user_updated_at`    | string                                          | false    |              |                                                                                                  |
| `username`           | string                                          | false    |              |                                                                                                  |

#### Enumerated Values

| Property | Value(s)              |
|----------|-----------------------|
| `status` | `active`, `suspended` |

## codersdk.OrganizationSyncSettings

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  },
  "organization_assign_default": true
}
```

### Properties

| Name                          | Type            | Required | Restrictions | Description                                                                                                                                                                         |
|-------------------------------|-----------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `field`                       | string          | false    |              | Field selects the claim field to be used as the created user's organizations. If the field is the empty string, then no organization updates will ever come from the OIDC provider. |
| `mapping`                     | object          | false    |              | Mapping maps from an OIDC claim --> Coder organization uuid                                                                                                                         |
| » `[any property]`            | array of string | false    |              |                                                                                                                                                                                     |
| `organization_assign_default` | boolean         | false    |              | Organization assign default will ensure the default org is always included for every user, regardless of their claims. This preserves legacy behavior.                              |

## codersdk.PaginatedGroup

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "source": "user",
  "total_member_count": 0
}
```

### Properties

| Name                        | Type                                         | Required | Restrictions | Description                                                                                                                                                              |
|-----------------------------|----------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `avatar_url`                | string                                       | false    |              |                                                                                                                                                                          |
| `display_name`              | string                                       | false    |              |                                                                                                                                                                          |
| `id`                        | string                                       | false    |              |                                                                                                                                                                          |
| `name`                      | string                                       | false    |              |                                                                                                                                                                          |
| `organization_display_name` | string                                       | false    |              |                                                                                                                                                                          |
| `organization_id`           | string                                       | false    |              |                                                                                                                                                                          |
| `organization_name`         | string                                       | false    |              |                                                                                                                                                                          |
| `quota_allowance`           | integer                                      | false    |              |                                                                                                                                                                          |
| `source`                    | [codersdk.GroupSource](#codersdkgroupsource) | false    |              |                                                                                                                                                                          |
| `total_member_count`        | integer                                      | false    |              | Total member count is the number of members in the group, shown even when the caller cannot read individual members. The roster itself is not returned by this endpoint. |

## codersdk.PaginatedGroupsResponse

```json
{
  "count": 0,
  "groups": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "source": "user",
      "total_member_count": 0
    }
  ]
}
```

### Properties

| Name     | Type                                                        | Required | Restrictions | Description |
|----------|-------------------------------------------------------------|----------|--------------|-------------|
| `count`  | integer                                                     | false    |              |             |
| `groups` | array of [codersdk.PaginatedGroup](#codersdkpaginatedgroup) | false    |              |             |

## codersdk.PaginatedMembersResponse

```json
{
  "count": 0,
  "members": [
    {
      "avatar_url": "string",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "string",
      "global_roles": [
        {
          "display_name": "string",
          "name": "string",
          "organization_id": "string"
        }
      ],
      "has_ai_seat": true,
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "roles": [
        {
          "display_name": "string",
          "name": "string",
          "organization_id": "string"
        }
      ],
      "status": "active",
      "updated_at": "2019-08-24T14:15:22Z",
      "user_created_at": "2019-08-24T14:15:22Z",
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
      "user_updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Properties

| Name      | Type                                                                                        | Required | Restrictions | Description |
|-----------|---------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `count`   | integer                                                                                     | false    |              |             |
| `members` | array of [codersdk.OrganizationMemberWithUserData](#codersdkorganizationmemberwithuserdata) | false    |              |             |

## codersdk.ParameterFormType

```json
""
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                            |
|---------------------------------------------------------------------------------------------------------------------|
| ``, `checkbox`, `dropdown`, `error`, `input`, `multi-select`, `radio`, `slider`, `switch`, `tag-select`, `textarea` |

## codersdk.PatchGroupIDPSyncConfigRequest

```json
{
  "auto_create_missing_groups": true,
  "field": "string",
  "regex_filter": {}
}
```

### Properties

| Name                         | Type                           | Required | Restrictions | Description |
|------------------------------|--------------------------------|----------|--------------|-------------|
| `auto_create_missing_groups` | boolean                        | false    |              |             |
| `field`                      | string                         | false    |              |             |
| `regex_filter`               | [regexp.Regexp](#regexpregexp) | false    |              |             |

## codersdk.PatchGroupIDPSyncMappingRequest

```json
{
  "add": [
    {
      "gets": "string",
      "given": "string"
    }
  ],
  "remove": [
    {
      "gets": "string",
      "given": "string"
    }
  ]
}
```

### Properties

| Name      | Type            | Required | Restrictions | Description                                              |
|-----------|-----------------|----------|--------------|----------------------------------------------------------|
| `add`     | array of object | false    |              |                                                          |
| `» gets`  | string          | false    |              | The ID of the Coder resource the user should be added to |
| `» given` | string          | false    |              | The IdP claim the user has                               |
| `remove`  | array of object | false    |              |                                                          |
| `» gets`  | string          | false    |              | The ID of the Coder resource the user should be added to |
| `» given` | string          | false    |              | The IdP claim the user has                               |

## codersdk.PatchGroupRequest

```json
{
  "add_users": [
    "string"
  ],
  "avatar_url": "string",
  "display_name": "string",
  "name": "string",
  "quota_allowance": 0,
  "remove_users": [
    "string"
  ]
}
```

### Properties

| Name              | Type            | Required | Restrictions | Description |
|-------------------|-----------------|----------|--------------|-------------|
| `add_users`       | array of string | false    |              |             |
| `avatar_url`      | string          | false    |              |             |
| `display_name`    | string          | false    |              |             |
| `name`            | string          | false    |              |             |
| `quota_allowance` | integer         | false    |              |             |
| `remove_users`    | array of string | false    |              |             |

## codersdk.PatchOrganizationIDPSyncConfigRequest

```json
{
  "assign_default": true,
  "field": "string"
}
```

### Properties

| Name             | Type    | Required | Restrictions | Description |
|------------------|---------|----------|--------------|-------------|
| `assign_default` | boolean | false    |              |             |
| `field`          | string  | false    |              |             |

## codersdk.PatchOrganizationIDPSyncMappingRequest

```json
{
  "add": [
    {
      "gets": "string",
      "given": "string"
    }
  ],
  "remove": [
    {
      "gets": "string",
      "given": "string"
    }
  ]
}
```

### Properties

| Name      | Type            | Required | Restrictions | Description                                              |
|-----------|-----------------|----------|--------------|----------------------------------------------------------|
| `add`     | array of object | false    |              |                                                          |
| `» gets`  | string          | false    |              | The ID of the Coder resource the user should be added to |
| `» given` | string          | false    |              | The IdP claim the user has                               |
| `remove`  | array of object | false    |              |                                                          |
| `» gets`  | string          | false    |              | The ID of the Coder resource the user should be added to |
| `» given` | string          | false    |              | The IdP claim the user has                               |

## codersdk.PatchRoleIDPSyncConfigRequest

```json
{
  "field": "string"
}
```

### Properties

| Name    | Type   | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `field` | string | false    |              |             |

## codersdk.PatchRoleIDPSyncMappingRequest

```json
{
  "add": [
    {
      "gets": "string",
      "given": "string"
    }
  ],
  "remove": [
    {
      "gets": "string",
      "given": "string"
    }
  ]
}
```

### Properties

| Name      | Type            | Required | Restrictions | Description                                              |
|-----------|-----------------|----------|--------------|----------------------------------------------------------|
| `add`     | array of object | false    |              |                                                          |
| `» gets`  | string          | false    |              | The ID of the Coder resource the user should be added to |
| `» given` | string          | false    |              | The IdP claim the user has                               |
| `remove`  | array of object | false    |              |                                                          |
| `» gets`  | string          | false    |              | The ID of the Coder resource the user should be added to |
| `» given` | string          | false    |              | The IdP claim the user has                               |

## codersdk.PatchTemplateVersionRequest

```json
{
  "message": "string",
  "name": "string"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description |
|-----------|--------|----------|--------------|-------------|
| `message` | string | false    |              |             |
| `name`    | string | false    |              |             |

## codersdk.PatchWorkspaceProxy

```json
{
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "regenerate_token": true
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description |
|--------------------|---------|----------|--------------|-------------|
| `display_name`     | string  | true     |              |             |
| `icon`             | string  | true     |              |             |
| `id`               | string  | true     |              |             |
| `name`             | string  | true     |              |             |
| `regenerate_token` | boolean | false    |              |             |

## codersdk.Permission

```json
{
  "action": "application_connect",
  "negate": true,
  "resource_type": "*"
}
```

### Properties

| Name            | Type                                           | Required | Restrictions | Description                             |
|-----------------|------------------------------------------------|----------|--------------|-----------------------------------------|
| `action`        | [codersdk.RBACAction](#codersdkrbacaction)     | false    |              |                                         |
| `negate`        | boolean                                        | false    |              | Negate makes this a negative permission |
| `resource_type` | [codersdk.RBACResource](#codersdkrbacresource) | false    |              |                                         |

## codersdk.PostOAuth2ProviderAppRequest

```json
{
  "callback_url": "string",
  "icon": "string",
  "name": "string",
  "redirect_uris": [
    "string"
  ],
  "scope": "string"
}
```

### Properties

| Name            | Type            | Required | Restrictions | Description                                                                                                                                                      |
|-----------------|-----------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `callback_url`  | string          | false    |              | Deprecated: send redirect_uris instead. If both are sent, callback_url must equal the first entry of redirect_uris.                                              |
| `icon`          | string          | false    |              |                                                                                                                                                                  |
| `name`          | string          | true     |              |                                                                                                                                                                  |
| `redirect_uris` | array of string | false    |              | Redirect uris is the ordered list of URIs the app may redirect to. The first entry is the primary. Required, unless the deprecated callback_url is sent instead. |
| `scope`         | string          | false    |              | Scope is the space-separated list of scopes this app's tokens may be granted. Leave empty, or omit, for unrestricted.                                            |

## codersdk.PostWorkspaceUsageRequest

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "app_name": "string"
}
```

### Properties

| Name       | Type   | Required | Restrictions | Description                                                                                                                                                                        |
|------------|--------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_id` | string | false    |              |                                                                                                                                                                                    |
| `app_name` | string | false    |              | App name is any name for the app reporting usage. The server normalizes it at ingestion, so a new app needs no server change. The UsageAppName constants are the well-known names. |

## codersdk.PprofConfig

```json
{
  "address": {
    "host": "string",
    "port": "string"
  },
  "enable": true
}
```

### Properties

| Name      | Type                                 | Required | Restrictions | Description |
|-----------|--------------------------------------|----------|--------------|-------------|
| `address` | [serpent.HostPort](#serpenthostport) | false    |              |             |
| `enable`  | boolean                              | false    |              |             |

## codersdk.PrebuildsConfig

```json
{
  "failure_hard_limit": 0,
  "reconciliation_backoff_interval": 0,
  "reconciliation_backoff_lookback": 0,
  "reconciliation_interval": 0
}
```

### Properties

| Name                              | Type    | Required | Restrictions | Description                                                                                                                                                                                                                                                                                       |
|-----------------------------------|---------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `failure_hard_limit`              | integer | false    |              | Failure hard limit defines the maximum number of consecutive failed prebuild attempts allowed before a preset is considered to be in a hard limit state. When a preset hits this limit, no new prebuilds will be created until the limit is reset. FailureHardLimit is disabled when set to zero. |
| `reconciliation_backoff_interval` | integer | false    |              | Reconciliation backoff interval specifies the amount of time to increase the backoff interval when errors occur during reconciliation.                                                                                                                                                            |
| `reconciliation_backoff_lookback` | integer | false    |              | Reconciliation backoff lookback determines the time window to look back when calculating the number of failed prebuilds, which influences the backoff strategy.                                                                                                                                   |
| `reconciliation_interval`         | integer | false    |              | Reconciliation interval defines how often the workspace prebuilds state should be reconciled.                                                                                                                                                                                                     |

## codersdk.PrebuildsSettings

```json
{
  "reconciliation_paused": true
}
```

### Properties

| Name                    | Type    | Required | Restrictions | Description |
|-------------------------|---------|----------|--------------|-------------|
| `reconciliation_paused` | boolean | false    |              |             |

## codersdk.PremiumFunnelEventRequest

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "source": "aibridge_session_threads",
  "variant": "premium"
}
```

### Properties

| Name      | Type                                                           | Required | Restrictions | Description                                                                                       |
|-----------|----------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------|
| `id`      | string                                                         | true     |              | ID identifies this click, and doubles as the attribution token that a later trial signup reports. |
| `source`  | [codersdk.PremiumFunnelSource](#codersdkpremiumfunnelsource)   | true     |              |                                                                                                   |
| `variant` | [codersdk.PremiumFunnelVariant](#codersdkpremiumfunnelvariant) | true     |              |                                                                                                   |

## codersdk.PremiumFunnelSource

```json
"aibridge_session_threads"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                                                                                                                                                                                                      |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ai_gateway_keys`, `ai_governance`, `aibridge_session_threads`, `aibridge_sessions`, `appearance`, `audit_log`, `browser_only`, `connection_log`, `custom_roles`, `direct`, `external_auth`, `groups`, `idp_org_sync`, `idp_sync`, `multiple_organizations`, `observability`, `provisioner_keys`, `provisioners`, `template_permissions`, `workspace_proxies` |

## codersdk.PremiumFunnelVariant

```json
"premium"
```

### Properties

#### Enumerated Values

| Value(s)                            |
|-------------------------------------|
| `ai_governance`, `premium`, `small` |

## codersdk.Preset

```json
{
  "default": true,
  "description": "string",
  "desiredPrebuildInstances": 0,
  "icon": "string",
  "id": "string",
  "name": "string",
  "parameters": [
    {
      "name": "string",
      "value": "string"
    }
  ]
}
```

### Properties

| Name                       | Type                                                          | Required | Restrictions | Description |
|----------------------------|---------------------------------------------------------------|----------|--------------|-------------|
| `default`                  | boolean                                                       | false    |              |             |
| `description`              | string                                                        | false    |              |             |
| `desiredPrebuildInstances` | integer                                                       | false    |              |             |
| `icon`                     | string                                                        | false    |              |             |
| `id`                       | string                                                        | false    |              |             |
| `name`                     | string                                                        | false    |              |             |
| `parameters`               | array of [codersdk.PresetParameter](#codersdkpresetparameter) | false    |              |             |

## codersdk.PresetParameter

```json
{
  "name": "string",
  "value": "string"
}
```

### Properties

| Name    | Type   | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `name`  | string | false    |              |             |
| `value` | string | false    |              |             |

## codersdk.PreviewParameter

```json
{
  "default_value": {
    "valid": true,
    "value": "string"
  },
  "description": "string",
  "diagnostics": [
    {
      "detail": "string",
      "extra": {
        "code": "string"
      },
      "severity": "error",
      "summary": "string"
    }
  ],
  "display_name": "string",
  "ephemeral": true,
  "form_type": "",
  "icon": "string",
  "mutable": true,
  "name": "string",
  "options": [
    {
      "description": "string",
      "icon": "string",
      "name": "string",
      "value": {
        "valid": true,
        "value": "string"
      }
    }
  ],
  "order": 0,
  "required": true,
  "styling": {
    "disabled": true,
    "label": "string",
    "mask_input": true,
    "placeholder": "string"
  },
  "type": "string",
  "validations": [
    {
      "validation_error": "string",
      "validation_max": 0,
      "validation_min": 0,
      "validation_monotonic": "string",
      "validation_regex": "string"
    }
  ],
  "value": {
    "valid": true,
    "value": "string"
  }
}
```

### Properties

| Name            | Type                                                                                | Required | Restrictions | Description                             |
|-----------------|-------------------------------------------------------------------------------------|----------|--------------|-----------------------------------------|
| `default_value` | [codersdk.NullHCLString](#codersdknullhclstring)                                    | false    |              |                                         |
| `description`   | string                                                                              | false    |              |                                         |
| `diagnostics`   | array of [codersdk.FriendlyDiagnostic](#codersdkfriendlydiagnostic)                 | false    |              |                                         |
| `display_name`  | string                                                                              | false    |              |                                         |
| `ephemeral`     | boolean                                                                             | false    |              |                                         |
| `form_type`     | [codersdk.ParameterFormType](#codersdkparameterformtype)                            | false    |              |                                         |
| `icon`          | string                                                                              | false    |              |                                         |
| `mutable`       | boolean                                                                             | false    |              |                                         |
| `name`          | string                                                                              | false    |              |                                         |
| `options`       | array of [codersdk.PreviewParameterOption](#codersdkpreviewparameteroption)         | false    |              |                                         |
| `order`         | integer                                                                             | false    |              | legacy_variable_name was removed (= 14) |
| `required`      | boolean                                                                             | false    |              |                                         |
| `styling`       | [codersdk.PreviewParameterStyling](#codersdkpreviewparameterstyling)                | false    |              |                                         |
| `type`          | [codersdk.OptionType](#codersdkoptiontype)                                          | false    |              |                                         |
| `validations`   | array of [codersdk.PreviewParameterValidation](#codersdkpreviewparametervalidation) | false    |              |                                         |
| `value`         | [codersdk.NullHCLString](#codersdknullhclstring)                                    | false    |              |                                         |

## codersdk.PreviewParameterOption

```json
{
  "description": "string",
  "icon": "string",
  "name": "string",
  "value": {
    "valid": true,
    "value": "string"
  }
}
```

### Properties

| Name          | Type                                             | Required | Restrictions | Description |
|---------------|--------------------------------------------------|----------|--------------|-------------|
| `description` | string                                           | false    |              |             |
| `icon`        | string                                           | false    |              |             |
| `name`        | string                                           | false    |              |             |
| `value`       | [codersdk.NullHCLString](#codersdknullhclstring) | false    |              |             |

## codersdk.PreviewParameterStyling

```json
{
  "disabled": true,
  "label": "string",
  "mask_input": true,
  "placeholder": "string"
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `disabled`    | boolean | false    |              |             |
| `label`       | string  | false    |              |             |
| `mask_input`  | boolean | false    |              |             |
| `placeholder` | string  | false    |              |             |

## codersdk.PreviewParameterValidation

```json
{
  "validation_error": "string",
  "validation_max": 0,
  "validation_min": 0,
  "validation_monotonic": "string",
  "validation_regex": "string"
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description                             |
|------------------------|---------|----------|--------------|-----------------------------------------|
| `validation_error`     | string  | false    |              |                                         |
| `validation_max`       | integer | false    |              |                                         |
| `validation_min`       | integer | false    |              |                                         |
| `validation_monotonic` | string  | false    |              |                                         |
| `validation_regex`     | string  | false    |              | All validation attributes are optional. |

## codersdk.PrometheusConfig

```json
{
  "address": {
    "host": "string",
    "port": "string"
  },
  "aggregate_agent_stats_by": [
    "string"
  ],
  "collect_agent_stats": true,
  "collect_db_metrics": true,
  "enable": true
}
```

### Properties

| Name                       | Type                                 | Required | Restrictions | Description |
|----------------------------|--------------------------------------|----------|--------------|-------------|
| `address`                  | [serpent.HostPort](#serpenthostport) | false    |              |             |
| `aggregate_agent_stats_by` | array of string                      | false    |              |             |
| `collect_agent_stats`      | boolean                              | false    |              |             |
| `collect_db_metrics`       | boolean                              | false    |              |             |
| `enable`                   | boolean                              | false    |              |             |

## codersdk.ProposeChatTitleResponse

```json
{
  "title": "string"
}
```

### Properties

| Name    | Type   | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `title` | string | false    |              |             |

## codersdk.ProvisionerConfig

```json
{
  "daemon_poll_interval": 0,
  "daemon_poll_jitter": 0,
  "daemon_psk": "string",
  "daemon_types": [
    "string"
  ],
  "daemons": 0,
  "disable_module_cache": true,
  "force_cancel_interval": 0
}
```

### Properties

| Name                    | Type            | Required | Restrictions | Description                                                                                                                                                |
|-------------------------|-----------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `daemon_poll_interval`  | integer         | false    |              |                                                                                                                                                            |
| `daemon_poll_jitter`    | integer         | false    |              |                                                                                                                                                            |
| `daemon_psk`            | string          | false    |              |                                                                                                                                                            |
| `daemon_types`          | array of string | false    |              |                                                                                                                                                            |
| `daemons`               | integer         | false    |              | Daemons is the number of built-in terraform provisioners.                                                                                                  |
| `disable_module_cache`  | boolean         | false    |              | Disable module cache disables the reuse of Terraform modules cached at template import for every template in the deployment. Templates cannot opt back in. |
| `force_cancel_interval` | integer         | false    |              |                                                                                                                                                            |

## codersdk.ProvisionerDaemon

```json
{
  "api_version": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "current_job": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "status": "pending",
    "template_display_name": "string",
    "template_icon": "string",
    "template_name": "string"
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
  "key_name": "string",
  "last_seen_at": "2019-08-24T14:15:22Z",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "previous_job": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "status": "pending",
    "template_display_name": "string",
    "template_icon": "string",
    "template_name": "string"
  },
  "provisioners": [
    "string"
  ],
  "status": "offline",
  "tags": {
    "property1": "string",
    "property2": "string"
  },
  "version": "string"
}
```

### Properties

| Name               | Type                                                                 | Required | Restrictions | Description      |
|--------------------|----------------------------------------------------------------------|----------|--------------|------------------|
| `api_version`      | string                                                               | false    |              |                  |
| `created_at`       | string                                                               | false    |              |                  |
| `current_job`      | [codersdk.ProvisionerDaemonJob](#codersdkprovisionerdaemonjob)       | false    |              |                  |
| `id`               | string                                                               | false    |              |                  |
| `key_id`           | string                                                               | false    |              |                  |
| `key_name`         | string                                                               | false    |              | Optional fields. |
| `last_seen_at`     | string                                                               | false    |              |                  |
| `name`             | string                                                               | false    |              |                  |
| `organization_id`  | string                                                               | false    |              |                  |
| `previous_job`     | [codersdk.ProvisionerDaemonJob](#codersdkprovisionerdaemonjob)       | false    |              |                  |
| `provisioners`     | array of string                                                      | false    |              |                  |
| `status`           | [codersdk.ProvisionerDaemonStatus](#codersdkprovisionerdaemonstatus) | false    |              |                  |
| `tags`             | object                                                               | false    |              |                  |
| » `[any property]` | string                                                               | false    |              |                  |
| `version`          | string                                                               | false    |              |                  |

#### Enumerated Values

| Property | Value(s)                  |
|----------|---------------------------|
| `status` | `busy`, `idle`, `offline` |

## codersdk.ProvisionerDaemonJob

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "status": "pending",
  "template_display_name": "string",
  "template_icon": "string",
  "template_name": "string"
}
```

### Properties

| Name                    | Type                                                           | Required | Restrictions | Description |
|-------------------------|----------------------------------------------------------------|----------|--------------|-------------|
| `id`                    | string                                                         | false    |              |             |
| `status`                | [codersdk.ProvisionerJobStatus](#codersdkprovisionerjobstatus) | false    |              |             |
| `template_display_name` | string                                                         | false    |              |             |
| `template_icon`         | string                                                         | false    |              |             |
| `template_name`         | string                                                         | false    |              |             |

#### Enumerated Values

| Property | Value(s)                                                             |
|----------|----------------------------------------------------------------------|
| `status` | `canceled`, `canceling`, `failed`, `pending`, `running`, `succeeded` |

## codersdk.ProvisionerDaemonStatus

```json
"offline"
```

### Properties

#### Enumerated Values

| Value(s)                  |
|---------------------------|
| `busy`, `idle`, `offline` |

## codersdk.ProvisionerJob

```json
{
  "available_workers": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "canceled_at": "2019-08-24T14:15:22Z",
  "completed_at": "2019-08-24T14:15:22Z",
  "created_at": "2019-08-24T14:15:22Z",
  "error": "string",
  "error_code": "REQUIRED_TEMPLATE_VARIABLES",
  "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "input": {
    "error": "string",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
  },
  "logs_overflowed": true,
  "metadata": {
    "template_display_name": "string",
    "template_icon": "string",
    "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
    "template_name": "string",
    "template_version_name": "string",
    "workspace_build_transition": "start",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string"
  },
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "queue_position": 0,
  "queue_size": 0,
  "started_at": "2019-08-24T14:15:22Z",
  "status": "pending",
  "tags": {
    "property1": "string",
    "property2": "string"
  },
  "type": "template_version_import",
  "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
  "worker_name": "string"
}
```

### Properties

| Name                | Type                                                               | Required | Restrictions | Description |
|---------------------|--------------------------------------------------------------------|----------|--------------|-------------|
| `available_workers` | array of string                                                    | false    |              |             |
| `canceled_at`       | string                                                             | false    |              |             |
| `completed_at`      | string                                                             | false    |              |             |
| `created_at`        | string                                                             | false    |              |             |
| `error`             | string                                                             | false    |              |             |
| `error_code`        | [codersdk.JobErrorCode](#codersdkjoberrorcode)                     | false    |              |             |
| `file_id`           | string                                                             | false    |              |             |
| `id`                | string                                                             | false    |              |             |
| `initiator_id`      | string                                                             | false    |              |             |
| `input`             | [codersdk.ProvisionerJobInput](#codersdkprovisionerjobinput)       | false    |              |             |
| `logs_overflowed`   | boolean                                                            | false    |              |             |
| `metadata`          | [codersdk.ProvisionerJobMetadata](#codersdkprovisionerjobmetadata) | false    |              |             |
| `organization_id`   | string                                                             | false    |              |             |
| `queue_position`    | integer                                                            | false    |              |             |
| `queue_size`        | integer                                                            | false    |              |             |
| `started_at`        | string                                                             | false    |              |             |
| `status`            | [codersdk.ProvisionerJobStatus](#codersdkprovisionerjobstatus)     | false    |              |             |
| `tags`              | object                                                             | false    |              |             |
| » `[any property]`  | string                                                             | false    |              |             |
| `type`              | [codersdk.ProvisionerJobType](#codersdkprovisionerjobtype)         | false    |              |             |
| `worker_id`         | string                                                             | false    |              |             |
| `worker_name`       | string                                                             | false    |              |             |

#### Enumerated Values

| Property     | Value(s)                                                             |
|--------------|----------------------------------------------------------------------|
| `error_code` | `INSUFFICIENT_QUOTA`, `REQUIRED_TEMPLATE_VARIABLES`                  |
| `status`     | `canceled`, `canceling`, `failed`, `pending`, `running`, `succeeded` |

## codersdk.ProvisionerJobInput

```json
{
  "error": "string",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
}
```

### Properties

| Name                  | Type   | Required | Restrictions | Description |
|-----------------------|--------|----------|--------------|-------------|
| `error`               | string | false    |              |             |
| `template_version_id` | string | false    |              |             |
| `workspace_build_id`  | string | false    |              |             |

## codersdk.ProvisionerJobLog

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": 0,
  "log_level": "trace",
  "log_source": "provisioner_daemon",
  "output": "string",
  "stage": "string"
}
```

### Properties

| Name         | Type                                     | Required | Restrictions | Description |
|--------------|------------------------------------------|----------|--------------|-------------|
| `created_at` | string                                   | false    |              |             |
| `id`         | integer                                  | false    |              |             |
| `log_level`  | [codersdk.LogLevel](#codersdkloglevel)   | false    |              |             |
| `log_source` | [codersdk.LogSource](#codersdklogsource) | false    |              |             |
| `output`     | string                                   | false    |              |             |
| `stage`      | string                                   | false    |              |             |

#### Enumerated Values

| Property    | Value(s)                                  |
|-------------|-------------------------------------------|
| `log_level` | `debug`, `error`, `info`, `trace`, `warn` |

## codersdk.ProvisionerJobMetadata

```json
{
  "template_display_name": "string",
  "template_icon": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_name": "string",
  "template_version_name": "string",
  "workspace_build_transition": "start",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
  "workspace_name": "string"
}
```

### Properties

| Name                         | Type                                                         | Required | Restrictions | Description |
|------------------------------|--------------------------------------------------------------|----------|--------------|-------------|
| `template_display_name`      | string                                                       | false    |              |             |
| `template_icon`              | string                                                       | false    |              |             |
| `template_id`                | string                                                       | false    |              |             |
| `template_name`              | string                                                       | false    |              |             |
| `template_version_name`      | string                                                       | false    |              |             |
| `workspace_build_transition` | [codersdk.WorkspaceTransition](#codersdkworkspacetransition) | false    |              |             |
| `workspace_id`               | string                                                       | false    |              |             |
| `workspace_name`             | string                                                       | false    |              |             |

## codersdk.ProvisionerJobStatus

```json
"pending"
```

### Properties

#### Enumerated Values

| Value(s)                                                                        |
|---------------------------------------------------------------------------------|
| `canceled`, `canceling`, `failed`, `pending`, `running`, `succeeded`, `unknown` |

## codersdk.ProvisionerJobType

```json
"template_version_import"
```

### Properties

#### Enumerated Values

| Value(s)                                                                 |
|--------------------------------------------------------------------------|
| `template_version_dry_run`, `template_version_import`, `workspace_build` |

## codersdk.ProvisionerKey

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "organization": "452c1a86-a0af-475b-b03f-724878b0f387",
  "tags": {
    "property1": "string",
    "property2": "string"
  }
}
```

### Properties

| Name           | Type                                                       | Required | Restrictions | Description |
|----------------|------------------------------------------------------------|----------|--------------|-------------|
| `created_at`   | string                                                     | false    |              |             |
| `id`           | string                                                     | false    |              |             |
| `name`         | string                                                     | false    |              |             |
| `organization` | string                                                     | false    |              |             |
| `tags`         | [codersdk.ProvisionerKeyTags](#codersdkprovisionerkeytags) | false    |              |             |

## codersdk.ProvisionerKeyDaemons

```json
{
  "daemons": [
    {
      "api_version": "string",
      "created_at": "2019-08-24T14:15:22Z",
      "current_job": {
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "status": "pending",
        "template_display_name": "string",
        "template_icon": "string",
        "template_name": "string"
      },
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
      "key_name": "string",
      "last_seen_at": "2019-08-24T14:15:22Z",
      "name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "previous_job": {
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "status": "pending",
        "template_display_name": "string",
        "template_icon": "string",
        "template_name": "string"
      },
      "provisioners": [
        "string"
      ],
      "status": "offline",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "version": "string"
    }
  ],
  "key": {
    "created_at": "2019-08-24T14:15:22Z",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "organization": "452c1a86-a0af-475b-b03f-724878b0f387",
    "tags": {
      "property1": "string",
      "property2": "string"
    }
  }
}
```

### Properties

| Name      | Type                                                              | Required | Restrictions | Description |
|-----------|-------------------------------------------------------------------|----------|--------------|-------------|
| `daemons` | array of [codersdk.ProvisionerDaemon](#codersdkprovisionerdaemon) | false    |              |             |
| `key`     | [codersdk.ProvisionerKey](#codersdkprovisionerkey)                | false    |              |             |

## codersdk.ProvisionerKeyTags

```json
{
  "property1": "string",
  "property2": "string"
}
```

### Properties

| Name             | Type   | Required | Restrictions | Description |
|------------------|--------|----------|--------------|-------------|
| `[any property]` | string | false    |              |             |

## codersdk.ProvisionerLogLevel

```json
"debug"
```

### Properties

#### Enumerated Values

| Value(s) |
|----------|
| `debug`  |

## codersdk.ProvisionerStorageMethod

```json
"file"
```

### Properties

#### Enumerated Values

| Value(s) |
|----------|
| `file`   |

## codersdk.ProvisionerTiming

```json
{
  "action": "string",
  "ended_at": "2019-08-24T14:15:22Z",
  "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
  "resource": "string",
  "source": "string",
  "stage": "init",
  "started_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name         | Type                                         | Required | Restrictions | Description |
|--------------|----------------------------------------------|----------|--------------|-------------|
| `action`     | string                                       | false    |              |             |
| `ended_at`   | string                                       | false    |              |             |
| `job_id`     | string                                       | false    |              |             |
| `resource`   | string                                       | false    |              |             |
| `source`     | string                                       | false    |              |             |
| `stage`      | [codersdk.TimingStage](#codersdktimingstage) | false    |              |             |
| `started_at` | string                                       | false    |              |             |

## codersdk.ProxyHealthReport

```json
{
  "errors": [
    "string"
  ],
  "warnings": [
    "string"
  ]
}
```

### Properties

| Name       | Type            | Required | Restrictions | Description                                                                              |
|------------|-----------------|----------|--------------|------------------------------------------------------------------------------------------|
| `errors`   | array of string | false    |              | Errors are problems that prevent the workspace proxy from being healthy                  |
| `warnings` | array of string | false    |              | Warnings do not prevent the workspace proxy from being healthy, but should be addressed. |

## codersdk.ProxyHealthStatus

```json
"ok"
```

### Properties

#### Enumerated Values

| Value(s)                                         |
|--------------------------------------------------|
| `ok`, `unhealthy`, `unreachable`, `unregistered` |

## codersdk.PutExperimentRuleRequest

```json
{
  "condition": "string",
  "expected_revision": 0,
  "mode": "inherit"
}
```

### Properties

| Name                | Type                                                       | Required | Restrictions | Description                                                                                                                                                                                              |
|---------------------|------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `condition`         | string                                                     | false    |              | Condition is required for the condition mode and must be empty otherwise.                                                                                                                                |
| `expected_revision` | integer                                                    | false    |              | Expected revision must equal the current revision of the stored rule, or zero when no rule is stored or the stored rule has no readable positive revision. A different revision fails with 409 Conflict. |
| `mode`              | [codersdk.ExperimentRuleMode](#codersdkexperimentrulemode) | false    |              |                                                                                                                                                                                                          |

#### Enumerated Values

| Property | Value(s)                            |
|----------|-------------------------------------|
| `mode`   | `condition`, `inherit`, `off`, `on` |

## codersdk.PutExtendWorkspaceRequest

```json
{
  "deadline": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name       | Type   | Required | Restrictions | Description |
|------------|--------|----------|--------------|-------------|
| `deadline` | string | true     |              |             |

## codersdk.PutOAuth2ProviderAppRequest

```json
{
  "callback_url": "string",
  "icon": "string",
  "name": "string",
  "redirect_uris": [
    "string"
  ],
  "scope": "string"
}
```

### Properties

| Name            | Type            | Required | Restrictions | Description                                                                                                                                                                                                                                                           |
|-----------------|-----------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `callback_url`  | string          | false    |              | Deprecated: send redirect_uris instead. If both are sent, callback_url must equal the first entry of redirect_uris.                                                                                                                                                   |
| `icon`          | string          | false    |              | Icon replaces the app's stored icon. Omitting it clears the stored icon rather than leaving it unchanged.                                                                                                                                                             |
| `name`          | string          | true     |              |                                                                                                                                                                                                                                                                       |
| `redirect_uris` | array of string | false    |              | Redirect uris is the ordered list of URIs the app may redirect to. The first entry is the primary. Omit both this and callback_url to keep the stored redirect URIs. Other fields are replaced. Sending an empty list is an error, not a way to keep the stored list. |
| `scope`         | string          | false    |              | Scope replaces the app's current allowlist. Omit to leave the existing allowlist untouched. Set to an empty string to clear it, making the app unrestricted.                                                                                                          |

## codersdk.RBACAction

```json
"application_connect"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                                                                       |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `application_connect`, `assign`, `create`, `create_agent`, `delete`, `delete_agent`, `read`, `read_personal`, `share`, `ssh`, `start`, `stop`, `unassign`, `update`, `update_agent`, `update_personal`, `use`, `view_insights` |

## codersdk.RBACResource

```json
"*"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `chat_model_config`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `mcp_server_config`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_build_orchestration`, `workspace_dormant`, `workspace_proxy` |

## codersdk.RateLimitConfig

```json
{
  "api": 0,
  "disable_all": true
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `api`         | integer | false    |              |             |
| `disable_all` | boolean | false    |              |             |

## codersdk.ReducedUser

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Properties

| Name                 | Type                                       | Required | Restrictions | Description                                                                                |
|----------------------|--------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------|
| `avatar_url`         | string                                     | false    |              |                                                                                            |
| `created_at`         | string                                     | true     |              |                                                                                            |
| `email`              | string                                     | true     |              |                                                                                            |
| `id`                 | string                                     | true     |              |                                                                                            |
| `is_service_account` | boolean                                    | false    |              |                                                                                            |
| `last_seen_at`       | string                                     | false    |              |                                                                                            |
| `login_type`         | [codersdk.LoginType](#codersdklogintype)   | false    |              |                                                                                            |
| `name`               | string                                     | false    |              |                                                                                            |
| `status`             | [codersdk.UserStatus](#codersdkuserstatus) | false    |              |                                                                                            |
| `theme_preference`   | string                                     | false    |              | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. |
| `updated_at`         | string                                     | false    |              |                                                                                            |
| `username`           | string                                     | true     |              |                                                                                            |

#### Enumerated Values

| Property | Value(s)              |
|----------|-----------------------|
| `status` | `active`, `suspended` |

## codersdk.Region

```json
{
  "display_name": "string",
  "healthy": true,
  "icon_url": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "path_app_url": "string",
  "wildcard_hostname": "string"
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description                                                                                                                                                                       |
|---------------------|---------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `display_name`      | string  | false    |              |                                                                                                                                                                                   |
| `healthy`           | boolean | false    |              |                                                                                                                                                                                   |
| `icon_url`          | string  | false    |              |                                                                                                                                                                                   |
| `id`                | string  | false    |              |                                                                                                                                                                                   |
| `name`              | string  | false    |              |                                                                                                                                                                                   |
| `path_app_url`      | string  | false    |              | Path app URL is the URL to the base path for path apps. Optional unless wildcard_hostname is set. E.g. https://us.example.com                                                     |
| `wildcard_hostname` | string  | false    |              | Wildcard hostname is the wildcard hostname for subdomain apps. E.g. *.us.example.com E.g.*--suffix.au.example.com Optional. Does not need to be on the same domain as PathAppURL. |

## codersdk.RegionsResponse-codersdk_Region

```json
{
  "regions": [
    {
      "display_name": "string",
      "healthy": true,
      "icon_url": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "path_app_url": "string",
      "wildcard_hostname": "string"
    }
  ]
}
```

### Properties

| Name      | Type                                        | Required | Restrictions | Description |
|-----------|---------------------------------------------|----------|--------------|-------------|
| `regions` | array of [codersdk.Region](#codersdkregion) | false    |              |             |

## codersdk.RegionsResponse-codersdk_WorkspaceProxy

```json
{
  "regions": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "deleted": true,
      "derp_enabled": true,
      "derp_only": true,
      "display_name": "string",
      "healthy": true,
      "icon_url": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "path_app_url": "string",
      "status": {
        "checked_at": "2019-08-24T14:15:22Z",
        "report": {
          "errors": [
            "string"
          ],
          "warnings": [
            "string"
          ]
        },
        "status": "ok"
      },
      "updated_at": "2019-08-24T14:15:22Z",
      "version": "string",
      "wildcard_hostname": "string"
    }
  ]
}
```

### Properties

| Name      | Type                                                        | Required | Restrictions | Description |
|-----------|-------------------------------------------------------------|----------|--------------|-------------|
| `regions` | array of [codersdk.WorkspaceProxy](#codersdkworkspaceproxy) | false    |              |             |

## codersdk.Replica

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "database_latency": 0,
  "error": "string",
  "hostname": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "region_id": 0,
  "relay_address": "string"
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description                                                        |
|--------------------|---------|----------|--------------|--------------------------------------------------------------------|
| `created_at`       | string  | false    |              | Created at is the timestamp when the replica was first seen.       |
| `database_latency` | integer | false    |              | Database latency is the latency in microseconds to the database.   |
| `error`            | string  | false    |              | Error is the replica error.                                        |
| `hostname`         | string  | false    |              | Hostname is the hostname of the replica.                           |
| `id`               | string  | false    |              | ID is the unique identifier for the replica.                       |
| `region_id`        | integer | false    |              | Region ID is the region of the replica.                            |
| `relay_address`    | string  | false    |              | Relay address is the accessible address to relay DERP connections. |

## codersdk.RequestOneTimePasscodeRequest

```json
{
  "email": "user@example.com"
}
```

### Properties

| Name    | Type   | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `email` | string | true     |              |             |

## codersdk.ResolveAutostartResponse

```json
{
  "parameter_mismatch": true
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `parameter_mismatch` | boolean | false    |              |             |

## codersdk.ResourceType

```json
"template"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ai_gateway_key`, `ai_provider`, `ai_provider_key`, `ai_seat`, `api_key`, `chat`, `chat_instruction_settings`, `chat_model_config`, `chat_operational_settings`, `convert_login`, `custom_role`, `experiment_rule`, `git_ssh_key`, `group`, `group_ai_budget`, `health_settings`, `idp_sync_settings_group`, `idp_sync_settings_organization`, `idp_sync_settings_role`, `license`, `mcp_server_config`, `notification_template`, `notifications_settings`, `oauth2_provider_app`, `oauth2_provider_app_secret`, `oauth2_provider_settings`, `organization`, `organization_member`, `prebuilds_settings`, `task`, `template`, `template_version`, `user`, `user_ai_budget_override`, `user_secret`, `user_skill`, `workspace`, `workspace_agent`, `workspace_app`, `workspace_build`, `workspace_proxy` |

## codersdk.Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Properties

| Name          | Type                                                          | Required | Restrictions | Description                                                                                                                                                                                                                        |
|---------------|---------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `detail`      | string                                                        | false    |              | Detail is a debug message that provides further insight into why the action failed. This information can be technical and a regular golang err.Error() text. - "database: too many open connections" - "stat: too many open files" |
| `message`     | string                                                        | false    |              | Message is an actionable message that depicts actions the request took. These messages should be fully formed sentences with proper punctuation. Examples: - "A user has been created." - "Failed to create a user."               |
| `validations` | array of [codersdk.ValidationError](#codersdkvalidationerror) | false    |              | Validations are form field-specific friendly error messages. They will be shown on a form field in the UI. These can also be used to add additional context if there is a set of errors in the primary 'Message'.                  |

## codersdk.RetentionConfig

```json
{
  "api_keys": 0,
  "audit_logs": 0,
  "boundary_logs": 0,
  "connection_logs": 0,
  "workspace_agent_logs": 0
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description                                                                                                                                                                                                                                                                          |
|------------------------|---------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api_keys`             | integer | false    |              | Api keys controls how long expired API keys are retained before being deleted. Keys are only deleted if they have been expired for at least this duration. Defaults to 7 days to preserve existing behavior.                                                                         |
| `audit_logs`           | integer | false    |              | Audit logs controls how long audit log entries are retained. Set to 0 to disable (keep indefinitely).                                                                                                                                                                                |
| `boundary_logs`        | integer | false    |              | Boundary logs controls how long boundary audit log entries are retained. Boundary logs record every HTTP request processed by a Boundary confinement proxy. Set to 0 to disable automatic deletion (keep indefinitely). Adjust to match your organization's regulatory requirements. |
| `connection_logs`      | integer | false    |              | Connection logs controls how long connection log entries are retained. Set to 0 to disable (keep indefinitely).                                                                                                                                                                      |
| `workspace_agent_logs` | integer | false    |              | Workspace agent logs controls how long workspace agent logs are retained. Logs are deleted if the agent hasn't connected within this period. Logs from the latest build are always retained regardless of age. Defaults to 7 days to preserve existing behavior.                     |

## codersdk.Role

```json
{
  "display_name": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_member_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "organization_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "site_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ],
  "user_permissions": [
    {
      "action": "application_connect",
      "negate": true,
      "resource_type": "*"
    }
  ]
}
```

### Properties

| Name                              | Type                                                | Required | Restrictions | Description                                                                                            |
|-----------------------------------|-----------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------|
| `display_name`                    | string                                              | false    |              |                                                                                                        |
| `name`                            | string                                              | false    |              |                                                                                                        |
| `organization_id`                 | string                                              | false    |              |                                                                                                        |
| `organization_member_permissions` | array of [codersdk.Permission](#codersdkpermission) | false    |              | Organization member permissions are specific for the organization in the field 'OrganizationID' above. |
| `organization_permissions`        | array of [codersdk.Permission](#codersdkpermission) | false    |              | Organization permissions are specific for the organization in the field 'OrganizationID' above.        |
| `site_permissions`                | array of [codersdk.Permission](#codersdkpermission) | false    |              |                                                                                                        |
| `user_permissions`                | array of [codersdk.Permission](#codersdkpermission) | false    |              |                                                                                                        |

## codersdk.RoleSyncSettings

```json
{
  "field": "string",
  "mapping": {
    "property1": [
      "string"
    ],
    "property2": [
      "string"
    ]
  }
}
```

### Properties

| Name               | Type            | Required | Restrictions | Description                                                                                                                            |
|--------------------|-----------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------|
| `field`            | string          | false    |              | Field is the name of the claim field that specifies what organization roles a user should be given. If empty, no roles will be synced. |
| `mapping`          | object          | false    |              | Mapping is a map from OIDC groups to Coder organization roles.                                                                         |
| » `[any property]` | array of string | false    |              |                                                                                                                                        |

## codersdk.SSHConfig

```json
{
  "deploymentName": "string",
  "sshconfigOptions": [
    "string"
  ]
}
```

### Properties

| Name               | Type            | Required | Restrictions | Description                                                                                         |
|--------------------|-----------------|----------|--------------|-----------------------------------------------------------------------------------------------------|
| `deploymentName`   | string          | false    |              | Deploymentname is the config-ssh Hostname prefix                                                    |
| `sshconfigOptions` | array of string | false    |              | Sshconfigoptions are additional options to add to the ssh config file. This will override defaults. |

## codersdk.SSHConfigResponse

```json
{
  "hostname_prefix": "string",
  "hostname_suffix": "string",
  "ssh_config_options": {
    "property1": "string",
    "property2": "string"
  }
}
```

### Properties

| Name                 | Type   | Required | Restrictions | Description                                                                                                           |
|----------------------|--------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------|
| `hostname_prefix`    | string | false    |              | Hostname prefix is the prefix we append to workspace names for SSH hostnames. Deprecated: use HostnameSuffix instead. |
| `hostname_suffix`    | string | false    |              | Hostname suffix is the suffix to append to workspace names for SSH hostnames.                                         |
| `ssh_config_options` | object | false    |              |                                                                                                                       |
| » `[any property]`   | string | false    |              |                                                                                                                       |

## codersdk.SecretsFileFormat

```json
"env"
```

### Properties

#### Enumerated Values

| Value(s)              |
|-----------------------|
| `env`, `json`, `yaml` |

## codersdk.ServerSentEvent

```json
{
  "data": null,
  "type": "ping"
}
```

### Properties

| Name   | Type                                                         | Required | Restrictions | Description |
|--------|--------------------------------------------------------------|----------|--------------|-------------|
| `data` | any                                                          | false    |              |             |
| `type` | [codersdk.ServerSentEventType](#codersdkserversenteventtype) | false    |              |             |

## codersdk.ServerSentEventType

```json
"ping"
```

### Properties

#### Enumerated Values

| Value(s)                |
|-------------------------|
| `data`, `error`, `ping` |

## codersdk.SessionCountApp

```json
{
  "count": 0,
  "display_name": "string",
  "family": "vscode",
  "icon": "string"
}
```

### Properties

| Name           | Type                                             | Required | Restrictions | Description                                                                                      |
|----------------|--------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------|
| `count`        | integer                                          | false    |              |                                                                                                  |
| `display_name` | string                                           | false    |              | Display name is the registry's name for a known app, otherwise the normalized identifier itself. |
| `family`       | [codersdk.AppFamilyName](#codersdkappfamilyname) | false    |              | Family is the group this app totals under.                                                       |
| `icon`         | string                                           | false    |              | Icon is a bundled path under /icon/, empty if the app has none.                                  |

## codersdk.SessionCountDeploymentStats

```json
{
  "apps": {
    "property1": {
      "count": 0,
      "display_name": "string",
      "family": "vscode",
      "icon": "string"
    },
    "property2": {
      "count": 0,
      "display_name": "string",
      "family": "vscode",
      "icon": "string"
    }
  },
  "jetbrains": 0,
  "reconnecting_pty": 0,
  "ssh": 0,
  "vscode": 0
}
```

### Properties

| Name               | Type                                                 | Required | Restrictions | Description                                                                                                                                    |
|--------------------|------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------|
| `apps`             | object                                               | false    |              | Apps holds one entry per reported app name, each carrying the family it totals under. The fields below duplicate those totals for one release. |
| » `[any property]` | [codersdk.SessionCountApp](#codersdksessioncountapp) | false    |              |                                                                                                                                                |
| `jetbrains`        | integer                                              | false    |              | Deprecated: total Apps by Family instead.                                                                                                      |
| `reconnecting_pty` | integer                                              | false    |              | Deprecated: total Apps by Family instead.                                                                                                      |
| `ssh`              | integer                                              | false    |              | Deprecated: total Apps by Family instead.                                                                                                      |
| `vscode`           | integer                                              | false    |              | Deprecated: total Apps by Family instead.                                                                                                      |

## codersdk.SessionLifetime

```json
{
  "default_duration": 0,
  "default_token_lifetime": 0,
  "disable_expiry_refresh": true,
  "max_admin_token_lifetime": 0,
  "max_token_lifetime": 0,
  "refresh_default_duration": 0
}
```

### Properties

| Name                       | Type    | Required | Restrictions | Description                                                                                                                                                                            |
|----------------------------|---------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `default_duration`         | integer | false    |              | Default duration is only for browser, workspace app and oauth sessions.                                                                                                                |
| `default_token_lifetime`   | integer | false    |              |                                                                                                                                                                                        |
| `disable_expiry_refresh`   | boolean | false    |              | Disable expiry refresh will disable automatically refreshing api keys when they are used from the api. This means the api key lifetime at creation is the lifetime of the api key.     |
| `max_admin_token_lifetime` | integer | false    |              |                                                                                                                                                                                        |
| `max_token_lifetime`       | integer | false    |              |                                                                                                                                                                                        |
| `refresh_default_duration` | integer | false    |              | Refresh default duration is the default lifetime for OAuth2 refresh tokens. This should generally be longer than access token lifetimes to allow refreshing after access token expiry. |

## codersdk.ShareableWorkspaceOwners

```json
"none"
```

### Properties

#### Enumerated Values

| Value(s)                               |
|----------------------------------------|
| `everyone`, `none`, `service_accounts` |

## codersdk.SharedWorkspaceActor

```json
{
  "actor_type": "group",
  "avatar_url": "http://example.com",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "roles": [
    "admin"
  ]
}
```

### Properties

| Name         | Type                                                                   | Required | Restrictions | Description |
|--------------|------------------------------------------------------------------------|----------|--------------|-------------|
| `actor_type` | [codersdk.SharedWorkspaceActorType](#codersdksharedworkspaceactortype) | false    |              |             |
| `avatar_url` | string                                                                 | false    |              |             |
| `id`         | string                                                                 | false    |              |             |
| `name`       | string                                                                 | false    |              |             |
| `roles`      | array of [codersdk.WorkspaceRole](#codersdkworkspacerole)              | false    |              |             |

#### Enumerated Values

| Property     | Value(s)        |
|--------------|-----------------|
| `actor_type` | `group`, `user` |

## codersdk.SharedWorkspaceActorType

```json
"group"
```

### Properties

#### Enumerated Values

| Value(s)        |
|-----------------|
| `group`, `user` |

## codersdk.SlimRole

```json
{
  "display_name": "string",
  "name": "string",
  "organization_id": "string"
}
```

### Properties

| Name              | Type   | Required | Restrictions | Description |
|-------------------|--------|----------|--------------|-------------|
| `display_name`    | string | false    |              |             |
| `name`            | string | false    |              |             |
| `organization_id` | string | false    |              |             |

## codersdk.StatsCollectionConfig

```json
{
  "usage_stats": {
    "enable": true
  }
}
```

### Properties

| Name          | Type                                                   | Required | Restrictions | Description |
|---------------|--------------------------------------------------------|----------|--------------|-------------|
| `usage_stats` | [codersdk.UsageStatsConfig](#codersdkusagestatsconfig) | false    |              |             |

## codersdk.SubmitToolResultsRequest

```json
{
  "results": [
    {
      "is_error": true,
      "output": [
        0
      ],
      "tool_call_id": "string"
    }
  ]
}
```

### Properties

| Name      | Type                                                | Required | Restrictions | Description |
|-----------|-----------------------------------------------------|----------|--------------|-------------|
| `results` | array of [codersdk.ToolResult](#codersdktoolresult) | false    |              |             |

## codersdk.SupportConfig

```json
{
  "links": {
    "value": [
      {
        "icon": "bug",
        "location": "navbar",
        "name": "string",
        "target": "string"
      }
    ]
  }
}
```

### Properties

| Name    | Type                                                                                 | Required | Restrictions | Description |
|---------|--------------------------------------------------------------------------------------|----------|--------------|-------------|
| `links` | [serpent.Struct-array_codersdk_LinkConfig](#serpentstruct-array_codersdk_linkconfig) | false    |              |             |

## codersdk.SwaggerConfig

```json
{
  "enable": true
}
```

### Properties

| Name     | Type    | Required | Restrictions | Description |
|----------|---------|----------|--------------|-------------|
| `enable` | boolean | false    |              |             |

## codersdk.TLSConfig

```json
{
  "address": {
    "host": "string",
    "port": "string"
  },
  "allow_insecure_ciphers": true,
  "cert_file": [
    "string"
  ],
  "client_auth": "string",
  "client_ca_file": "string",
  "client_cert_file": "string",
  "client_key_file": "string",
  "enable": true,
  "key_file": [
    "string"
  ],
  "min_version": "string",
  "redirect_http": true,
  "supported_ciphers": [
    "string"
  ]
}
```

### Properties

| Name                     | Type                                 | Required | Restrictions | Description |
|--------------------------|--------------------------------------|----------|--------------|-------------|
| `address`                | [serpent.HostPort](#serpenthostport) | false    |              |             |
| `allow_insecure_ciphers` | boolean                              | false    |              |             |
| `cert_file`              | array of string                      | false    |              |             |
| `client_auth`            | string                               | false    |              |             |
| `client_ca_file`         | string                               | false    |              |             |
| `client_cert_file`       | string                               | false    |              |             |
| `client_key_file`        | string                               | false    |              |             |
| `enable`                 | boolean                              | false    |              |             |
| `key_file`               | array of string                      | false    |              |             |
| `min_version`            | string                               | false    |              |             |
| `redirect_http`          | boolean                              | false    |              |             |
| `supported_ciphers`      | array of string                      | false    |              |             |

## codersdk.TelemetryConfig

```json
{
  "enable": true,
  "trace": true,
  "url": {
    "forceQuery": true,
    "fragment": "string",
    "host": "string",
    "omitHost": true,
    "opaque": "string",
    "path": "string",
    "rawFragment": "string",
    "rawPath": "string",
    "rawQuery": "string",
    "scheme": "string",
    "user": {}
  }
}
```

### Properties

| Name     | Type                       | Required | Restrictions | Description |
|----------|----------------------------|----------|--------------|-------------|
| `enable` | boolean                    | false    |              |             |
| `trace`  | boolean                    | false    |              |             |
| `url`    | [serpent.URL](#serpenturl) | false    |              |             |

## codersdk.Template

```json
{
  "active_user_count": 0,
  "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "build_time_stats": {
    "property1": {
      "p50": 123,
      "p95": 146
    },
    "property2": {
      "p50": 123,
      "p95": 146
    }
  },
  "cors_behavior": "simple",
  "created_at": "2019-08-24T14:15:22Z",
  "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
  "created_by_name": "string",
  "default_ttl_ms": 0,
  "deleted": true,
  "deprecated": true,
  "deprecation_message": "string",
  "description": "string",
  "disable_module_cache": true,
  "display_name": "string",
  "failure_ttl_ms": 0,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "max_port_share_level": "owner",
  "module_cache_disabled_by_deployment": true,
  "name": "string",
  "organization_display_name": "string",
  "organization_icon": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "provisioner": "terraform",
  "require_active_version": true,
  "time_til_autostop_notify_ms": 0,
  "time_til_dormant_autodelete_ms": 0,
  "time_til_dormant_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "use_classic_parameter_flow": true
}
```

### Properties

| Name                                  | Type                                                                           | Required | Restrictions | Description                                                                                                                                                                                                                |
|---------------------------------------|--------------------------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `active_user_count`                   | integer                                                                        | false    |              | Active user count is set to -1 when loading.                                                                                                                                                                               |
| `active_version_id`                   | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `activity_bump_ms`                    | integer                                                                        | false    |              |                                                                                                                                                                                                                            |
| `agents_allowed`                      | boolean                                                                        | false    |              |                                                                                                                                                                                                                            |
| `allow_user_autostart`                | boolean                                                                        | false    |              | Allow user autostart and AllowUserAutostop are enterprise-only. Their values are only used if your license is entitled to use the advanced template scheduling feature.                                                    |
| `allow_user_autostop`                 | boolean                                                                        | false    |              |                                                                                                                                                                                                                            |
| `allow_user_cancel_workspace_jobs`    | boolean                                                                        | false    |              |                                                                                                                                                                                                                            |
| `allow_workspace_renames`             | boolean                                                                        | false    |              | Allow workspace renames permits users to rename workspaces built from this template. Renaming can be destructive for templates whose Terraform references the workspace name.                                              |
| `autostart_requirement`               | [codersdk.TemplateAutostartRequirement](#codersdktemplateautostartrequirement) | false    |              |                                                                                                                                                                                                                            |
| `autostop_requirement`                | [codersdk.TemplateAutostopRequirement](#codersdktemplateautostoprequirement)   | false    |              | Autostop requirement and AutostartRequirement are enterprise features. Its value is only used if your license is entitled to use the advanced template scheduling feature.                                                 |
| `build_time_stats`                    | [codersdk.TemplateBuildTimeStats](#codersdktemplatebuildtimestats)             | false    |              |                                                                                                                                                                                                                            |
| `cors_behavior`                       | [codersdk.CORSBehavior](#codersdkcorsbehavior)                                 | false    |              |                                                                                                                                                                                                                            |
| `created_at`                          | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `created_by_id`                       | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `created_by_name`                     | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `default_ttl_ms`                      | integer                                                                        | false    |              |                                                                                                                                                                                                                            |
| `deleted`                             | boolean                                                                        | false    |              |                                                                                                                                                                                                                            |
| `deprecated`                          | boolean                                                                        | false    |              |                                                                                                                                                                                                                            |
| `deprecation_message`                 | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `description`                         | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `disable_module_cache`                | boolean                                                                        | false    |              | Disable module cache disables the use of cached Terraform modules during provisioning for this template. It is read-only while ModuleCacheDisabledByDeployment is true.                                                    |
| `display_name`                        | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `failure_ttl_ms`                      | integer                                                                        | false    |              | Failure ttl ms TimeTilDormantMillis, and TimeTilDormantAutoDeleteMillis are enterprise-only. Their values are used if your license is entitled to use the advanced template scheduling feature.                            |
| `icon`                                | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `id`                                  | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `max_port_share_level`                | [codersdk.WorkspaceAgentPortShareLevel](#codersdkworkspaceagentportsharelevel) | false    |              |                                                                                                                                                                                                                            |
| `module_cache_disabled_by_deployment` | boolean                                                                        | false    |              | Module cache disabled by deployment reports that the deployment disables the Terraform module cache for every template. Templates cannot opt back in, so the effective state is disabled regardless of DisableModuleCache. |
| `name`                                | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `organization_display_name`           | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `organization_icon`                   | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `organization_id`                     | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `organization_name`                   | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `provisioner`                         | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `require_active_version`              | boolean                                                                        | false    |              | Require active version mandates that workspaces are built with the active template version.                                                                                                                                |
| `time_til_autostop_notify_ms`         | integer                                                                        | false    |              | Time til autostop notify ms is the duration before the workspace's autostop deadline at which a reminder notification is sent. 0 disables the notification.                                                                |
| `time_til_dormant_autodelete_ms`      | integer                                                                        | false    |              |                                                                                                                                                                                                                            |
| `time_til_dormant_ms`                 | integer                                                                        | false    |              |                                                                                                                                                                                                                            |
| `updated_at`                          | string                                                                         | false    |              |                                                                                                                                                                                                                            |
| `use_classic_parameter_flow`          | boolean                                                                        | false    |              |                                                                                                                                                                                                                            |

#### Enumerated Values

| Property      | Value(s)    |
|---------------|-------------|
| `provisioner` | `terraform` |

## codersdk.TemplateACL

```json
{
  "group": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "members": [
        {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        }
      ],
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "role": "admin",
      "source": "user",
      "total_member_count": 0
    }
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "has_ai_seat": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "organization_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "role": "admin",
      "roles": [
        {
          "display_name": "string",
          "name": "string",
          "organization_id": "string"
        }
      ],
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Properties

| Name    | Type                                                      | Required | Restrictions | Description |
|---------|-----------------------------------------------------------|----------|--------------|-------------|
| `group` | array of [codersdk.TemplateGroup](#codersdktemplategroup) | false    |              |             |
| `users` | array of [codersdk.TemplateUser](#codersdktemplateuser)   | false    |              |             |

## codersdk.TemplateAppUsage

```json
{
  "display_name": "Visual Studio Code",
  "icon": "string",
  "seconds": 80500,
  "slug": "vscode",
  "template_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "times_used": 2,
  "type": "builtin"
}
```

### Properties

| Name           | Type                                                   | Required | Restrictions | Description |
|----------------|--------------------------------------------------------|----------|--------------|-------------|
| `display_name` | string                                                 | false    |              |             |
| `icon`         | string                                                 | false    |              |             |
| `seconds`      | integer                                                | false    |              |             |
| `slug`         | string                                                 | false    |              |             |
| `template_ids` | array of string                                        | false    |              |             |
| `times_used`   | integer                                                | false    |              |             |
| `type`         | [codersdk.TemplateAppsType](#codersdktemplateappstype) | false    |              |             |

## codersdk.TemplateAppsType

```json
"builtin"
```

### Properties

#### Enumerated Values

| Value(s)         |
|------------------|
| `app`, `builtin` |

## codersdk.TemplateAutostartRequirement

```json
{
  "days_of_week": [
    "monday"
  ]
}
```

### Properties

| Name           | Type            | Required | Restrictions | Description                                                                                                                             |
|----------------|-----------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| `days_of_week` | array of string | false    |              | Days of week is a list of days of the week in which autostart is allowed to happen. If no days are specified, autostart is not allowed. |

## codersdk.TemplateAutostopRequirement

```json
{
  "days_of_week": [
    "monday"
  ],
  "weeks": 0
}
```

### Properties

|Name|Type|Required|Restrictions|Description|
|---|---|---|---|---|
|`days_of_week`|array of string|false||Days of week is a list of days of the week on which restarts are required. Restarts happen within the user's quiet hours (in their configured timezone). If no days are specified, restarts are not required. Weekdays cannot be specified twice.
Restarts will only happen on weekdays in this list on weeks which line up with Weeks.|
|`weeks`|integer|false||Weeks is the number of weeks between required restarts. Weeks are synced across all workspaces (and Coder deployments) using modulo math on a hardcoded epoch week of January 2nd, 2023 (the first Monday of 2023). Values of 0 or 1 indicate weekly restarts. Values of 2 indicate fortnightly restarts, etc.|

## codersdk.TemplateBuildTimeStats

```json
{
  "property1": {
    "p50": 123,
    "p95": 146
  },
  "property2": {
    "p50": 123,
    "p95": 146
  }
}
```

### Properties

| Name             | Type                                                 | Required | Restrictions | Description |
|------------------|------------------------------------------------------|----------|--------------|-------------|
| `[any property]` | [codersdk.TransitionStats](#codersdktransitionstats) | false    |              |             |

## codersdk.TemplateBuilderBase

```json
{
  "agents": [
    {
      "default": true,
      "display_name": "string",
      "name": "string"
    }
  ],
  "description": "string",
  "icon": "string",
  "id": "string",
  "name": "string",
  "os": "string",
  "prerequisites": "string",
  "variables": [
    {
      "default": [
        0
      ],
      "description": "string",
      "name": "string",
      "required": true,
      "sensitive": true,
      "type": "string"
    }
  ]
}
```

### Properties

| Name            | Type                                                                                      | Required | Restrictions | Description |
|-----------------|-------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `agents`        | array of [codersdk.TemplateBuilderBaseAgent](#codersdktemplatebuilderbaseagent)           | false    |              |             |
| `description`   | string                                                                                    | false    |              |             |
| `icon`          | string                                                                                    | false    |              |             |
| `id`            | string                                                                                    | false    |              |             |
| `name`          | string                                                                                    | false    |              |             |
| `os`            | string                                                                                    | false    |              |             |
| `prerequisites` | string                                                                                    | false    |              |             |
| `variables`     | array of [codersdk.TemplateBuilderModuleVariable](#codersdktemplatebuildermodulevariable) | false    |              |             |

## codersdk.TemplateBuilderBaseAgent

```json
{
  "default": true,
  "display_name": "string",
  "name": "string"
}
```

### Properties

| Name           | Type    | Required | Restrictions | Description                                                                     |
|----------------|---------|----------|--------------|---------------------------------------------------------------------------------|
| `default`      | boolean | false    |              | Default reports whether modules attach to this agent when they do not name one. |
| `display_name` | string  | false    |              |                                                                                 |
| `name`         | string  | false    |              |                                                                                 |

## codersdk.TemplateBuilderBasesResponse

```json
{
  "bases": [
    {
      "agents": [
        {
          "default": true,
          "display_name": "string",
          "name": "string"
        }
      ],
      "description": "string",
      "icon": "string",
      "id": "string",
      "name": "string",
      "os": "string",
      "prerequisites": "string",
      "variables": [
        {
          "default": [
            0
          ],
          "description": "string",
          "name": "string",
          "required": true,
          "sensitive": true,
          "type": "string"
        }
      ]
    }
  ]
}
```

### Properties

| Name    | Type                                                                  | Required | Restrictions | Description |
|---------|-----------------------------------------------------------------------|----------|--------------|-------------|
| `bases` | array of [codersdk.TemplateBuilderBase](#codersdktemplatebuilderbase) | false    |              |             |

## codersdk.TemplateBuilderComposeModule

```json
{
  "agent_name": "string",
  "id": "string",
  "variables": {
    "property1": "string",
    "property2": "string"
  }
}
```

### Properties

| Name               | Type   | Required | Restrictions | Description                                                                 |
|--------------------|--------|----------|--------------|-----------------------------------------------------------------------------|
| `agent_name`       | string | false    |              | Agent name targets a base coder_agent by name. Empty uses the base default. |
| `id`               | string | false    |              |                                                                             |
| `variables`        | object | false    |              |                                                                             |
| » `[any property]` | string | false    |              |                                                                             |

## codersdk.TemplateBuilderComposeRequest

```json
{
  "base_template_id": "string",
  "base_variable_values": {
    "property1": "string",
    "property2": "string"
  },
  "modules": [
    {
      "agent_name": "string",
      "id": "string",
      "variables": {
        "property1": "string",
        "property2": "string"
      }
    }
  ]
}
```

### Properties

| Name                   | Type                                                                                    | Required | Restrictions | Description |
|------------------------|-----------------------------------------------------------------------------------------|----------|--------------|-------------|
| `base_template_id`     | string                                                                                  | false    |              |             |
| `base_variable_values` | object                                                                                  | false    |              |             |
| » `[any property]`     | string                                                                                  | false    |              |             |
| `modules`              | array of [codersdk.TemplateBuilderComposeModule](#codersdktemplatebuildercomposemodule) | false    |              |             |

## codersdk.TemplateBuilderConfig

```json
{
  "disabled": true,
  "registry_url": "string"
}
```

### Properties

| Name           | Type    | Required | Restrictions | Description |
|----------------|---------|----------|--------------|-------------|
| `disabled`     | boolean | false    |              |             |
| `registry_url` | string  | false    |              |             |

## codersdk.TemplateBuilderCreateTemplateRequest

```json
{
  "base_template_id": "string",
  "base_variable_values": {
    "property1": "string",
    "property2": "string"
  },
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "modules": [
    {
      "agent_name": "string",
      "id": "string",
      "variables": {
        "property1": "string",
        "property2": "string"
      }
    }
  ],
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "provisioner_tags": {
    "property1": "string",
    "property2": "string"
  },
  "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82"
}
```

### Properties

| Name                   | Type                                                                                    | Required | Restrictions | Description                                                                                                                                                                                                |
|------------------------|-----------------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `base_template_id`     | string                                                                                  | false    |              |                                                                                                                                                                                                            |
| `base_variable_values` | object                                                                                  | false    |              |                                                                                                                                                                                                            |
| » `[any property]`     | string                                                                                  | false    |              |                                                                                                                                                                                                            |
| `description`          | string                                                                                  | false    |              |                                                                                                                                                                                                            |
| `display_name`         | string                                                                                  | false    |              |                                                                                                                                                                                                            |
| `icon`                 | string                                                                                  | false    |              |                                                                                                                                                                                                            |
| `modules`              | array of [codersdk.TemplateBuilderComposeModule](#codersdktemplatebuildercomposemodule) | false    |              |                                                                                                                                                                                                            |
| `name`                 | string                                                                                  | true     |              |                                                                                                                                                                                                            |
| `organization_id`      | string                                                                                  | true     |              |                                                                                                                                                                                                            |
| `provisioner_tags`     | object                                                                                  | false    |              |                                                                                                                                                                                                            |
| » `[any property]`     | string                                                                                  | false    |              |                                                                                                                                                                                                            |
| `session_id`           | string                                                                                  | false    |              | Session ID is the wizard session this request belongs to, as reported to POST /api/v2/templatebuilder/sessions. It is optional and used only to attribute a build failure to the session that produced it. |

## codersdk.TemplateBuilderCreateTemplateResponse

```json
{
  "template": {
    "active_user_count": 0,
    "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
    "activity_bump_ms": 0,
    "agents_allowed": true,
    "allow_user_autostart": true,
    "allow_user_autostop": true,
    "allow_user_cancel_workspace_jobs": true,
    "allow_workspace_renames": true,
    "autostart_requirement": {
      "days_of_week": [
        "monday"
      ]
    },
    "autostop_requirement": {
      "days_of_week": [
        "monday"
      ],
      "weeks": 0
    },
    "build_time_stats": {
      "property1": {
        "p50": 123,
        "p95": 146
      },
      "property2": {
        "p50": 123,
        "p95": 146
      }
    },
    "cors_behavior": "simple",
    "created_at": "2019-08-24T14:15:22Z",
    "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
    "created_by_name": "string",
    "default_ttl_ms": 0,
    "deleted": true,
    "deprecated": true,
    "deprecation_message": "string",
    "description": "string",
    "disable_module_cache": true,
    "display_name": "string",
    "failure_ttl_ms": 0,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "max_port_share_level": "owner",
    "module_cache_disabled_by_deployment": true,
    "name": "string",
    "organization_display_name": "string",
    "organization_icon": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_name": "string",
    "provisioner": "terraform",
    "require_active_version": true,
    "time_til_autostop_notify_ms": 0,
    "time_til_dormant_autodelete_ms": 0,
    "time_til_dormant_ms": 0,
    "updated_at": "2019-08-24T14:15:22Z",
    "use_classic_parameter_flow": true
  }
}
```

### Properties

| Name       | Type                                   | Required | Restrictions | Description |
|------------|----------------------------------------|----------|--------------|-------------|
| `template` | [codersdk.Template](#codersdktemplate) | false    |              |             |

## codersdk.TemplateBuilderModule

```json
{
  "category": "string",
  "compatible_os": [
    "string"
  ],
  "conflicts_with": [
    "string"
  ],
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "id": "string",
  "variables": [
    {
      "default": [
        0
      ],
      "description": "string",
      "name": "string",
      "required": true,
      "sensitive": true,
      "type": "string"
    }
  ],
  "version": "string"
}
```

### Properties

| Name             | Type                                                                                      | Required | Restrictions | Description |
|------------------|-------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `category`       | string                                                                                    | false    |              |             |
| `compatible_os`  | array of string                                                                           | false    |              |             |
| `conflicts_with` | array of string                                                                           | false    |              |             |
| `description`    | string                                                                                    | false    |              |             |
| `display_name`   | string                                                                                    | false    |              |             |
| `icon`           | string                                                                                    | false    |              |             |
| `id`             | string                                                                                    | false    |              |             |
| `variables`      | array of [codersdk.TemplateBuilderModuleVariable](#codersdktemplatebuildermodulevariable) | false    |              |             |
| `version`        | string                                                                                    | false    |              |             |

## codersdk.TemplateBuilderModuleVariable

```json
{
  "default": [
    0
  ],
  "description": "string",
  "name": "string",
  "required": true,
  "sensitive": true,
  "type": "string"
}
```

### Properties

| Name          | Type                                                                         | Required | Restrictions | Description |
|---------------|------------------------------------------------------------------------------|----------|--------------|-------------|
| `default`     | array of integer                                                             | false    |              |             |
| `description` | string                                                                       | false    |              |             |
| `name`        | string                                                                       | false    |              |             |
| `required`    | boolean                                                                      | false    |              |             |
| `sensitive`   | boolean                                                                      | false    |              |             |
| `type`        | [codersdk.TemplateBuilderVariableType](#codersdktemplatebuildervariabletype) | false    |              |             |

## codersdk.TemplateBuilderModulesResponse

```json
{
  "modules": [
    {
      "category": "string",
      "compatible_os": [
        "string"
      ],
      "conflicts_with": [
        "string"
      ],
      "description": "string",
      "display_name": "string",
      "icon": "string",
      "id": "string",
      "variables": [
        {
          "default": [
            0
          ],
          "description": "string",
          "name": "string",
          "required": true,
          "sensitive": true,
          "type": "string"
        }
      ],
      "version": "string"
    }
  ]
}
```

### Properties

| Name      | Type                                                                      | Required | Restrictions | Description |
|-----------|---------------------------------------------------------------------------|----------|--------------|-------------|
| `modules` | array of [codersdk.TemplateBuilderModule](#codersdktemplatebuildermodule) | false    |              |             |

## codersdk.TemplateBuilderSessionEventType

```json
"wizard_entry"
```

### Properties

#### Enumerated Values

| Value(s)                             |
|--------------------------------------|
| `compose_completion`, `wizard_entry` |

## codersdk.TemplateBuilderSessionRequest

```json
{
  "base_template_id": "string",
  "duration_seconds": 0,
  "event_type": "wizard_entry",
  "module_ids": [
    "string"
  ],
  "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  "success": true
}
```

### Properties

| Name               | Type                                                                                 | Required | Restrictions | Description |
|--------------------|--------------------------------------------------------------------------------------|----------|--------------|-------------|
| `base_template_id` | string                                                                               | false    |              |             |
| `duration_seconds` | number                                                                               | false    |              |             |
| `event_type`       | [codersdk.TemplateBuilderSessionEventType](#codersdktemplatebuildersessioneventtype) | true     |              |             |
| `module_ids`       | array of string                                                                      | false    |              |             |
| `session_id`       | string                                                                               | true     |              |             |
| `success`          | boolean                                                                              | false    |              |             |

#### Enumerated Values

| Property     | Value(s)                             |
|--------------|--------------------------------------|
| `event_type` | `compose_completion`, `wizard_entry` |

## codersdk.TemplateBuilderVariableType

```json
"string"
```

### Properties

#### Enumerated Values

| Value(s)                   |
|----------------------------|
| `bool`, `number`, `string` |

## codersdk.TemplateExample

```json
{
  "description": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "markdown": "string",
  "name": "string",
  "tags": [
    "string"
  ],
  "url": "string"
}
```

### Properties

| Name          | Type            | Required | Restrictions | Description |
|---------------|-----------------|----------|--------------|-------------|
| `description` | string          | false    |              |             |
| `icon`        | string          | false    |              |             |
| `id`          | string          | false    |              |             |
| `markdown`    | string          | false    |              |             |
| `name`        | string          | false    |              |             |
| `tags`        | array of string | false    |              |             |
| `url`         | string          | false    |              |             |

## codersdk.TemplateGroup

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "role": "admin",
  "source": "user",
  "total_member_count": 0
}
```

### Properties

| Name                        | Type                                                  | Required | Restrictions | Description                                                                                                                                                           |
|-----------------------------|-------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `avatar_url`                | string                                                | false    |              |                                                                                                                                                                       |
| `display_name`              | string                                                | false    |              |                                                                                                                                                                       |
| `id`                        | string                                                | false    |              |                                                                                                                                                                       |
| `members`                   | array of [codersdk.ReducedUser](#codersdkreduceduser) | false    |              |                                                                                                                                                                       |
| `name`                      | string                                                | false    |              |                                                                                                                                                                       |
| `organization_display_name` | string                                                | false    |              |                                                                                                                                                                       |
| `organization_id`           | string                                                | false    |              |                                                                                                                                                                       |
| `organization_name`         | string                                                | false    |              |                                                                                                                                                                       |
| `quota_allowance`           | integer                                               | false    |              |                                                                                                                                                                       |
| `role`                      | [codersdk.TemplateRole](#codersdktemplaterole)        | false    |              |                                                                                                                                                                       |
| `source`                    | [codersdk.GroupSource](#codersdkgroupsource)          | false    |              |                                                                                                                                                                       |
| `total_member_count`        | integer                                               | false    |              | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. |

#### Enumerated Values

| Property | Value(s)       |
|----------|----------------|
| `role`   | `admin`, `use` |

## codersdk.TemplateInsightsIntervalReport

```json
{
  "active_users": 14,
  "end_time": "2019-08-24T14:15:22Z",
  "interval": "week",
  "start_time": "2019-08-24T14:15:22Z",
  "template_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ]
}
```

### Properties

| Name           | Type                                                               | Required | Restrictions | Description |
|----------------|--------------------------------------------------------------------|----------|--------------|-------------|
| `active_users` | integer                                                            | false    |              |             |
| `end_time`     | string                                                             | false    |              |             |
| `interval`     | [codersdk.InsightsReportInterval](#codersdkinsightsreportinterval) | false    |              |             |
| `start_time`   | string                                                             | false    |              |             |
| `template_ids` | array of string                                                    | false    |              |             |

## codersdk.TemplateInsightsReport

```json
{
  "active_users": 22,
  "apps_usage": [
    {
      "display_name": "Visual Studio Code",
      "icon": "string",
      "seconds": 80500,
      "slug": "vscode",
      "template_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "times_used": 2,
      "type": "builtin"
    }
  ],
  "end_time": "2019-08-24T14:15:22Z",
  "parameters_usage": [
    {
      "description": "string",
      "display_name": "string",
      "name": "string",
      "options": [
        {
          "description": "string",
          "icon": "string",
          "name": "string",
          "value": "string"
        }
      ],
      "template_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "type": "string",
      "values": [
        {
          "count": 0,
          "value": "string"
        }
      ]
    }
  ],
  "start_time": "2019-08-24T14:15:22Z",
  "template_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ]
}
```

### Properties

| Name               | Type                                                                        | Required | Restrictions | Description |
|--------------------|-----------------------------------------------------------------------------|----------|--------------|-------------|
| `active_users`     | integer                                                                     | false    |              |             |
| `apps_usage`       | array of [codersdk.TemplateAppUsage](#codersdktemplateappusage)             | false    |              |             |
| `end_time`         | string                                                                      | false    |              |             |
| `parameters_usage` | array of [codersdk.TemplateParameterUsage](#codersdktemplateparameterusage) | false    |              |             |
| `start_time`       | string                                                                      | false    |              |             |
| `template_ids`     | array of string                                                             | false    |              |             |

## codersdk.TemplateInsightsResponse

```json
{
  "interval_reports": [
    {
      "active_users": 14,
      "end_time": "2019-08-24T14:15:22Z",
      "interval": "week",
      "start_time": "2019-08-24T14:15:22Z",
      "template_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ]
    }
  ],
  "report": {
    "active_users": 22,
    "apps_usage": [
      {
        "display_name": "Visual Studio Code",
        "icon": "string",
        "seconds": 80500,
        "slug": "vscode",
        "template_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "times_used": 2,
        "type": "builtin"
      }
    ],
    "end_time": "2019-08-24T14:15:22Z",
    "parameters_usage": [
      {
        "description": "string",
        "display_name": "string",
        "name": "string",
        "options": [
          {
            "description": "string",
            "icon": "string",
            "name": "string",
            "value": "string"
          }
        ],
        "template_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "type": "string",
        "values": [
          {
            "count": 0,
            "value": "string"
          }
        ]
      }
    ],
    "start_time": "2019-08-24T14:15:22Z",
    "template_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ]
  }
}
```

### Properties

| Name               | Type                                                                                        | Required | Restrictions | Description |
|--------------------|---------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `interval_reports` | array of [codersdk.TemplateInsightsIntervalReport](#codersdktemplateinsightsintervalreport) | false    |              |             |
| `report`           | [codersdk.TemplateInsightsReport](#codersdktemplateinsightsreport)                          | false    |              |             |

## codersdk.TemplateParameterUsage

```json
{
  "description": "string",
  "display_name": "string",
  "name": "string",
  "options": [
    {
      "description": "string",
      "icon": "string",
      "name": "string",
      "value": "string"
    }
  ],
  "template_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "type": "string",
  "values": [
    {
      "count": 0,
      "value": "string"
    }
  ]
}
```

### Properties

| Name           | Type                                                                                        | Required | Restrictions | Description |
|----------------|---------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `description`  | string                                                                                      | false    |              |             |
| `display_name` | string                                                                                      | false    |              |             |
| `name`         | string                                                                                      | false    |              |             |
| `options`      | array of [codersdk.TemplateVersionParameterOption](#codersdktemplateversionparameteroption) | false    |              |             |
| `template_ids` | array of string                                                                             | false    |              |             |
| `type`         | string                                                                                      | false    |              |             |
| `values`       | array of [codersdk.TemplateParameterValue](#codersdktemplateparametervalue)                 | false    |              |             |

## codersdk.TemplateParameterValue

```json
{
  "count": 0,
  "value": "string"
}
```

### Properties

| Name    | Type    | Required | Restrictions | Description |
|---------|---------|----------|--------------|-------------|
| `count` | integer | false    |              |             |
| `value` | string  | false    |              |             |

## codersdk.TemplateRole

```json
"admin"
```

### Properties

#### Enumerated Values

| Value(s)           |
|--------------------|
| ``, `admin`, `use` |

## codersdk.TemplateUser

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "role": "admin",
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Properties

| Name                 | Type                                            | Required | Restrictions | Description                                                                                      |
|----------------------|-------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------|
| `avatar_url`         | string                                          | false    |              |                                                                                                  |
| `created_at`         | string                                          | true     |              |                                                                                                  |
| `email`              | string                                          | true     |              |                                                                                                  |
| `has_ai_seat`        | boolean                                         | false    |              | Has ai seat intentionally omits omitempty so the API always includes the field, even when false. |
| `id`                 | string                                          | true     |              |                                                                                                  |
| `is_service_account` | boolean                                         | false    |              |                                                                                                  |
| `last_seen_at`       | string                                          | false    |              |                                                                                                  |
| `login_type`         | [codersdk.LoginType](#codersdklogintype)        | false    |              |                                                                                                  |
| `name`               | string                                          | false    |              |                                                                                                  |
| `organization_ids`   | array of string                                 | false    |              |                                                                                                  |
| `role`               | [codersdk.TemplateRole](#codersdktemplaterole)  | false    |              |                                                                                                  |
| `roles`              | array of [codersdk.SlimRole](#codersdkslimrole) | false    |              |                                                                                                  |
| `status`             | [codersdk.UserStatus](#codersdkuserstatus)      | false    |              |                                                                                                  |
| `theme_preference`   | string                                          | false    |              | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead.       |
| `updated_at`         | string                                          | false    |              |                                                                                                  |
| `username`           | string                                          | true     |              |                                                                                                  |

#### Enumerated Values

| Property | Value(s)              |
|----------|-----------------------|
| `role`   | `admin`, `use`        |
| `status` | `active`, `suspended` |

## codersdk.TemplateVersion

```json
{
  "archived": true,
  "created_at": "2019-08-24T14:15:22Z",
  "created_by": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "message": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "readme": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "UNSUPPORTED_WORKSPACES"
  ]
}
```

### Properties

| Name                   | Type                                                                        | Required | Restrictions | Description |
|------------------------|-----------------------------------------------------------------------------|----------|--------------|-------------|
| `archived`             | boolean                                                                     | false    |              |             |
| `created_at`           | string                                                                      | false    |              |             |
| `created_by`           | [codersdk.MinimalUser](#codersdkminimaluser)                                | false    |              |             |
| `has_external_agent`   | boolean                                                                     | false    |              |             |
| `id`                   | string                                                                      | false    |              |             |
| `job`                  | [codersdk.ProvisionerJob](#codersdkprovisionerjob)                          | false    |              |             |
| `matched_provisioners` | [codersdk.MatchedProvisioners](#codersdkmatchedprovisioners)                | false    |              |             |
| `message`              | string                                                                      | false    |              |             |
| `name`                 | string                                                                      | false    |              |             |
| `organization_id`      | string                                                                      | false    |              |             |
| `readme`               | string                                                                      | false    |              |             |
| `template_id`          | string                                                                      | false    |              |             |
| `updated_at`           | string                                                                      | false    |              |             |
| `warnings`             | array of [codersdk.TemplateVersionWarning](#codersdktemplateversionwarning) | false    |              |             |

## codersdk.TemplateVersionExternalAuth

```json
{
  "authenticate_url": "string",
  "authenticated": true,
  "display_icon": "string",
  "display_name": "string",
  "id": "string",
  "optional": true,
  "type": "string"
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description |
|--------------------|---------|----------|--------------|-------------|
| `authenticate_url` | string  | false    |              |             |
| `authenticated`    | boolean | false    |              |             |
| `display_icon`     | string  | false    |              |             |
| `display_name`     | string  | false    |              |             |
| `id`               | string  | false    |              |             |
| `optional`         | boolean | false    |              |             |
| `type`             | string  | false    |              |             |

## codersdk.TemplateVersionParameter

```json
{
  "default_value": "string",
  "description": "string",
  "description_plaintext": "string",
  "display_name": "string",
  "ephemeral": true,
  "form_type": "",
  "icon": "string",
  "mutable": true,
  "name": "string",
  "options": [
    {
      "description": "string",
      "icon": "string",
      "name": "string",
      "value": "string"
    }
  ],
  "required": true,
  "type": "string",
  "validation_error": "string",
  "validation_max": 0,
  "validation_min": 0,
  "validation_monotonic": "increasing",
  "validation_regex": "string"
}
```

### Properties

| Name                    | Type                                                                                        | Required | Restrictions | Description                                                                                        |
|-------------------------|---------------------------------------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------|
| `default_value`         | string                                                                                      | false    |              |                                                                                                    |
| `description`           | string                                                                                      | false    |              |                                                                                                    |
| `description_plaintext` | string                                                                                      | false    |              |                                                                                                    |
| `display_name`          | string                                                                                      | false    |              |                                                                                                    |
| `ephemeral`             | boolean                                                                                     | false    |              |                                                                                                    |
| `form_type`             | string                                                                                      | false    |              | Form type has an enum value of empty string, `""`. Keep the leading comma in the enums struct tag. |
| `icon`                  | string                                                                                      | false    |              |                                                                                                    |
| `mutable`               | boolean                                                                                     | false    |              |                                                                                                    |
| `name`                  | string                                                                                      | false    |              |                                                                                                    |
| `options`               | array of [codersdk.TemplateVersionParameterOption](#codersdktemplateversionparameteroption) | false    |              |                                                                                                    |
| `required`              | boolean                                                                                     | false    |              |                                                                                                    |
| `type`                  | string                                                                                      | false    |              |                                                                                                    |
| `validation_error`      | string                                                                                      | false    |              |                                                                                                    |
| `validation_max`        | integer                                                                                     | false    |              |                                                                                                    |
| `validation_min`        | integer                                                                                     | false    |              |                                                                                                    |
| `validation_monotonic`  | [codersdk.ValidationMonotonicOrder](#codersdkvalidationmonotonicorder)                      | false    |              |                                                                                                    |
| `validation_regex`      | string                                                                                      | false    |              |                                                                                                    |

#### Enumerated Values

| Property               | Value(s)                                                                                                            |
|------------------------|---------------------------------------------------------------------------------------------------------------------|
| `form_type`            | ``, `checkbox`, `dropdown`, `error`, `input`, `multi-select`, `radio`, `slider`, `switch`, `tag-select`, `textarea` |
| `type`                 | `bool`, `list(string)`, `number`, `string`                                                                          |
| `validation_monotonic` | `decreasing`, `increasing`                                                                                          |

## codersdk.TemplateVersionParameterOption

```json
{
  "description": "string",
  "icon": "string",
  "name": "string",
  "value": "string"
}
```

### Properties

| Name          | Type   | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `description` | string | false    |              |             |
| `icon`        | string | false    |              |             |
| `name`        | string | false    |              |             |
| `value`       | string | false    |              |             |

## codersdk.TemplateVersionVariable

```json
{
  "default_value": "string",
  "description": "string",
  "name": "string",
  "required": true,
  "sensitive": true,
  "type": "string",
  "value": "string"
}
```

### Properties

| Name            | Type    | Required | Restrictions | Description |
|-----------------|---------|----------|--------------|-------------|
| `default_value` | string  | false    |              |             |
| `description`   | string  | false    |              |             |
| `name`          | string  | false    |              |             |
| `required`      | boolean | false    |              |             |
| `sensitive`     | boolean | false    |              |             |
| `type`          | string  | false    |              |             |
| `value`         | string  | false    |              |             |

#### Enumerated Values

| Property | Value(s)                   |
|----------|----------------------------|
| `type`   | `bool`, `number`, `string` |

## codersdk.TemplateVersionWarning

```json
"UNSUPPORTED_WORKSPACES"
```

### Properties

#### Enumerated Values

| Value(s)                 |
|--------------------------|
| `UNSUPPORTED_WORKSPACES` |

## codersdk.TerminalFontName

```json
""
```

### Properties

#### Enumerated Values

| Value(s)                                                                            |
|-------------------------------------------------------------------------------------|
| ``, `fira-code`, `geist-mono`, `ibm-plex-mono`, `jetbrains-mono`, `source-code-pro` |

## codersdk.ThemeMode

```json
""
```

### Properties

#### Enumerated Values

| Value(s)             |
|----------------------|
| ``, `single`, `sync` |

## codersdk.ThinkingDisplayMode

```json
"auto"
```

### Properties

#### Enumerated Values

| Value(s)                                                 |
|----------------------------------------------------------|
| `always_collapsed`, `always_expanded`, `auto`, `preview` |

## codersdk.TimingStage

```json
"init"
```

### Properties

#### Enumerated Values

| Value(s)                                                             |
|----------------------------------------------------------------------|
| `apply`, `connect`, `cron`, `graph`, `init`, `plan`, `start`, `stop` |

## codersdk.TokenConfig

```json
{
  "max_token_lifetime": 0
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `max_token_lifetime` | integer | false    |              |             |

## codersdk.ToolResult

```json
{
  "is_error": true,
  "output": [
    0
  ],
  "tool_call_id": "string"
}
```

### Properties

| Name           | Type             | Required | Restrictions | Description |
|----------------|------------------|----------|--------------|-------------|
| `is_error`     | boolean          | false    |              |             |
| `output`       | array of integer | false    |              |             |
| `tool_call_id` | string           | false    |              |             |

## codersdk.TraceConfig

```json
{
  "capture_logs": true,
  "data_dog": true,
  "enable": true,
  "honeycomb_api_key": "string"
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `capture_logs`      | boolean | false    |              |             |
| `data_dog`          | boolean | false    |              |             |
| `enable`            | boolean | false    |              |             |
| `honeycomb_api_key` | string  | false    |              |             |

## codersdk.TransitionStats

```json
{
  "p50": 123,
  "p95": 146
}
```

### Properties

| Name  | Type    | Required | Restrictions | Description |
|-------|---------|----------|--------------|-------------|
| `p50` | integer | false    |              |             |
| `p95` | integer | false    |              |             |

## codersdk.UpdateAIProviderRequest

```json
{
  "api_keys": [
    {
      "api_key": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    }
  ],
  "base_url": "string",
  "display_name": "string",
  "enabled": true,
  "icon": "string",
  "settings": {}
}
```

### Properties

| Name           | Type                                                                      | Required | Restrictions | Description |
|----------------|---------------------------------------------------------------------------|----------|--------------|-------------|
| `api_keys`     | array of [codersdk.AIProviderKeyMutation](#codersdkaiproviderkeymutation) | false    |              |             |
| `base_url`     | string                                                                    | false    |              |             |
| `display_name` | string                                                                    | false    |              |             |
| `enabled`      | boolean                                                                   | false    |              |             |
| `icon`         | string                                                                    | false    |              |             |
| `settings`     | [codersdk.AIProviderSettings](#codersdkaiprovidersettings)                | false    |              |             |

## codersdk.UpdateActiveTemplateVersion

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}
```

### Properties

| Name | Type   | Required | Restrictions | Description |
|------|--------|----------|--------------|-------------|
| `id` | string | true     |              |             |

## codersdk.UpdateAppearanceConfig

```json
{
  "announcement_banners": [
    {
      "background_color": "string",
      "enabled": true,
      "message": "string"
    }
  ],
  "application_name": "string",
  "codernauts_enabled": true,
  "logo_url": "string",
  "service_banner": {
    "background_color": "string",
    "enabled": true,
    "message": "string"
  }
}
```

### Properties

| Name                   | Type                                                    | Required | Restrictions | Description                                                         |
|------------------------|---------------------------------------------------------|----------|--------------|---------------------------------------------------------------------|
| `announcement_banners` | array of [codersdk.BannerConfig](#codersdkbannerconfig) | false    |              |                                                                     |
| `application_name`     | string                                                  | false    |              |                                                                     |
| `codernauts_enabled`   | boolean                                                 | false    |              |                                                                     |
| `logo_url`             | string                                                  | false    |              |                                                                     |
| `service_banner`       | [codersdk.BannerConfig](#codersdkbannerconfig)          | false    |              | Deprecated: ServiceBanner has been replaced by AnnouncementBanners. |

## codersdk.UpdateChatACL

```json
{
  "group_roles": {
    "property1": "read",
    "property2": "read"
  },
  "user_roles": {
    "property1": "read",
    "property2": "read"
  }
}
```

### Properties

| Name               | Type                                   | Required | Restrictions | Description |
|--------------------|----------------------------------------|----------|--------------|-------------|
| `group_roles`      | object                                 | false    |              |             |
| » `[any property]` | [codersdk.ChatRole](#codersdkchatrole) | false    |              |             |
| `user_roles`       | object                                 | false    |              |             |
| » `[any property]` | [codersdk.ChatRole](#codersdkchatrole) | false    |              |             |

## codersdk.UpdateChatAutoArchiveDaysRequest

```json
{
  "auto_archive_days": 0
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `auto_archive_days` | integer | false    |              |             |

## codersdk.UpdateChatDebugLoggingAllowUsersRequest

```json
{
  "allow_users": true
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `allow_users` | boolean | false    |              |             |

## codersdk.UpdateChatDebugRetentionDaysRequest

```json
{
  "debug_retention_days": 0
}
```

### Properties

| Name                   | Type    | Required | Restrictions | Description |
|------------------------|---------|----------|--------------|-------------|
| `debug_retention_days` | integer | false    |              |             |

## codersdk.UpdateChatModelACLRequest

```json
{
  "group_roles": {
    "property1": "read",
    "property2": "read"
  },
  "user_roles": {
    "property1": "read",
    "property2": "read"
  }
}
```

### Properties

| Name               | Type                                   | Required | Restrictions | Description |
|--------------------|----------------------------------------|----------|--------------|-------------|
| `group_roles`      | object                                 | false    |              |             |
| » `[any property]` | [codersdk.ChatRole](#codersdkchatrole) | false    |              |             |
| `user_roles`       | object                                 | false    |              |             |
| » `[any property]` | [codersdk.ChatRole](#codersdkchatrole) | false    |              |             |

## codersdk.UpdateChatModelOverrideRequest

```json
{
  "model_config_id": "string",
  "reasoning_effort": "string"
}
```

### Properties

| Name               | Type   | Required | Restrictions | Description |
|--------------------|--------|----------|--------------|-------------|
| `model_config_id`  | string | false    |              |             |
| `reasoning_effort` | string | false    |              |             |

## codersdk.UpdateChatModelRequest

```json
{
  "ai_provider_id": "5a3b8ff9-20e7-4c37-ba1a-5b433e355819",
  "compression_threshold": 0,
  "context_limit": 0,
  "display_name": "string",
  "enabled": true,
  "is_default": true,
  "model": "string",
  "model_config": {
    "frequency_penalty": 0,
    "max_output_tokens": 0,
    "openai_config": {
      "reasoning_model": true,
      "use_responses_api": true
    },
    "presence_penalty": 0,
    "provider_options": {
      "anthropic": {
        "allowed_domains": [
          "string"
        ],
        "blocked_domains": [
          "string"
        ],
        "context_1m_enabled": true,
        "disable_parallel_tool_use": true,
        "send_reasoning": true,
        "thinking": {
          "budget_tokens": 0
        },
        "thinking_display": "string",
        "web_search_enabled": true
      },
      "google": {
        "cached_content": "string",
        "safety_settings": [
          {
            "category": "string",
            "threshold": "string"
          }
        ],
        "thinking_config": {
          "include_thoughts": true,
          "thinking_budget": 0,
          "thinking_level": "string"
        },
        "threshold": "string",
        "web_search_enabled": true
      },
      "openai": {
        "allowed_domains": [
          "string"
        ],
        "include": [
          "string"
        ],
        "instructions": "string",
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "max_completion_tokens": 0,
        "max_tool_calls": 0,
        "metadata": {
          "property1": null,
          "property2": null
        },
        "parallel_tool_calls": true,
        "prediction": {
          "property1": null,
          "property2": null
        },
        "prompt_cache_key": "string",
        "reasoning_mode": "string",
        "reasoning_summary": "string",
        "safety_identifier": "string",
        "search_context_size": "string",
        "service_tier": "string",
        "store": true,
        "strict_json_schema": true,
        "structured_outputs": true,
        "text_verbosity": "string",
        "top_log_probs": 0,
        "user": "string",
        "web_search_enabled": true
      },
      "openaicompat": {
        "user": "string"
      },
      "openrouter": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "include_usage": true,
        "log_probs": true,
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "parallel_tool_calls": true,
        "provider": {
          "allow_fallbacks": true,
          "data_collection": "string",
          "ignore": [
            "string"
          ],
          "only": [
            "string"
          ],
          "order": [
            "string"
          ],
          "quantizations": [
            "string"
          ],
          "require_parameters": true,
          "sort": "string"
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "user": "string"
      },
      "vercel": {
        "extra_body": {
          "property1": null,
          "property2": null
        },
        "logit_bias": {
          "property1": 0,
          "property2": 0
        },
        "logprobs": true,
        "parallel_tool_calls": true,
        "providerOptions": {
          "models": [
            "string"
          ],
          "order": [
            "string"
          ]
        },
        "reasoning": {
          "enabled": true,
          "exclude": true,
          "max_tokens": 0
        },
        "top_logprobs": 0,
        "user": "string"
      }
    },
    "reasoning_effort": {
      "default": "string",
      "max": "string"
    },
    "temperature": 0,
    "top_k": 0,
    "top_p": 0
  }
}
```

### Properties

| Name                    | Type                                                         | Required | Restrictions | Description |
|-------------------------|--------------------------------------------------------------|----------|--------------|-------------|
| `ai_provider_id`        | string                                                       | false    |              |             |
| `compression_threshold` | integer                                                      | false    |              |             |
| `context_limit`         | integer                                                      | false    |              |             |
| `display_name`          | string                                                       | false    |              |             |
| `enabled`               | boolean                                                      | false    |              |             |
| `is_default`            | boolean                                                      | false    |              |             |
| `model`                 | string                                                       | false    |              |             |
| `model_config`          | [codersdk.ChatModelCallConfig](#codersdkchatmodelcallconfig) | false    |              |             |

## codersdk.UpdateChatPersonalModelOverridesAdminSettingsRequest

```json
{
  "allow_users": true
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `allow_users` | boolean | false    |              |             |

## codersdk.UpdateChatPlanModeInstructionsRequest

```json
{
  "plan_mode_instructions": "string"
}
```

### Properties

| Name                     | Type   | Required | Restrictions | Description |
|--------------------------|--------|----------|--------------|-------------|
| `plan_mode_instructions` | string | false    |              |             |

## codersdk.UpdateChatRequest

```json
{
  "archived": true,
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "pin_order": 0,
  "plan_mode": "plan",
  "read": true,
  "title": "string",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Properties

| Name               | Type                                           | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                                                                                             |
|--------------------|------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `archived`         | boolean                                        | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `labels`           | object                                         | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| » `[any property]` | string                                         | false    |              |                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| `pin_order`        | integer                                        | false    |              | Pin order controls the chat's pinned state and position. - nil: no change to pin state. - 0: unpin the chat. - >0 (chat is unpinned): pin the chat, appending it to   the end of the pinned list. The specific value is   ignored; the server assigns the next available position. - >0 (chat is already pinned): move the chat to the   requested position, shifting neighbors as needed. The   value is clamped to [1, pinned_count]. |
| `plan_mode`        | [codersdk.ChatPlanMode](#codersdkchatplanmode) | false    |              | Plan mode switches the chat's persistent plan mode. nil: no change, ptr to "plan": enable, ptr to "": clear.                                                                                                                                                                                                                                                                                                                            |
|`read`|boolean|false||Read moves the owner's read cursor, which drives HasUnread. - nil: no change. - true: mark every existing message as read. - false: clear the cursor so the chat reads as unread again.
The cursor is owner-scoped, so only the chat owner may set this. Opening a chat's stream marks it read, so marking the chat the owner is currently viewing as unread does not persist.|
|`title`|string|false|||
|`workspace_id`|string|false|||

## codersdk.UpdateChatRetentionDaysRequest

```json
{
  "retention_days": 0
}
```

### Properties

| Name             | Type    | Required | Restrictions | Description |
|------------------|---------|----------|--------------|-------------|
| `retention_days` | integer | false    |              |             |

## codersdk.UpdateChatSystemPromptRequest

```json
{
  "include_default_system_prompt": true,
  "system_prompt": "string"
}
```

### Properties

| Name                            | Type    | Required | Restrictions | Description |
|---------------------------------|---------|----------|--------------|-------------|
| `include_default_system_prompt` | boolean | false    |              |             |
| `system_prompt`                 | string  | false    |              |             |

## codersdk.UpdateChatWorkspaceTTLRequest

```json
{
  "workspace_ttl_ms": 0
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description                                                                                                              |
|--------------------|---------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------|
| `workspace_ttl_ms` | integer | false    |              | Workspace ttl ms is the workspace TTL in milliseconds. Zero means disabled; the template's own autostop setting applies. |

## codersdk.UpdateCheckResponse

```json
{
  "current": true,
  "url": "string",
  "version": "string"
}
```

### Properties

| Name      | Type    | Required | Restrictions | Description                                                             |
|-----------|---------|----------|--------------|-------------------------------------------------------------------------|
| `current` | boolean | false    |              | Current indicates whether the server version is the same as the latest. |
| `url`     | string  | false    |              | URL to download the latest release of Coder.                            |
| `version` | string  | false    |              | Version is the semantic version for the latest release of Coder.        |

## codersdk.UpdateMCPServerConfigACLRequest

```json
{
  "group_roles": {
    "property1": "read",
    "property2": "read"
  },
  "user_roles": {
    "property1": "read",
    "property2": "read"
  }
}
```

### Properties

| Name               | Type                                                         | Required | Restrictions | Description |
|--------------------|--------------------------------------------------------------|----------|--------------|-------------|
| `group_roles`      | object                                                       | false    |              |             |
| » `[any property]` | [codersdk.MCPServerConfigRole](#codersdkmcpserverconfigrole) | false    |              |             |
| `user_roles`       | object                                                       | false    |              |             |
| » `[any property]` | [codersdk.MCPServerConfigRole](#codersdkmcpserverconfigrole) | false    |              |             |

## codersdk.UpdateMCPServerConfigRequest

```json
{
  "allow_in_plan_mode": true,
  "api_key_header": "string",
  "api_key_value": "string",
  "auth_type": "none",
  "availability": "force_on",
  "custom_headers": {
    "property1": "string",
    "property2": "string"
  },
  "description": "string",
  "display_name": "string",
  "enabled": true,
  "forward_coder_headers": true,
  "icon_url": "string",
  "model_intent": true,
  "oauth2_auth_url": "string",
  "oauth2_client_id": "string",
  "oauth2_client_secret": "string",
  "oauth2_revocation_url": "string",
  "oauth2_scopes": "string",
  "oauth2_token_url": "string",
  "signing_secret": "string",
  "slug": "string",
  "tool_allow_list": [
    "string"
  ],
  "tool_deny_list": [
    "string"
  ],
  "transport": "streamable_http",
  "url": "string"
}
```

### Properties

| Name                    | Type            | Required | Restrictions | Description                                                                                                             |
|-------------------------|-----------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------|
| `allow_in_plan_mode`    | boolean         | false    |              |                                                                                                                         |
| `api_key_header`        | string          | false    |              |                                                                                                                         |
| `api_key_value`         | string          | false    |              |                                                                                                                         |
| `auth_type`             | string          | false    |              |                                                                                                                         |
| `availability`          | string          | false    |              |                                                                                                                         |
| `custom_headers`        | object          | false    |              |                                                                                                                         |
| » `[any property]`      | string          | false    |              |                                                                                                                         |
| `description`           | string          | false    |              |                                                                                                                         |
| `display_name`          | string          | false    |              |                                                                                                                         |
| `enabled`               | boolean         | false    |              |                                                                                                                         |
| `forward_coder_headers` | boolean         | false    |              | Forward coder headers when set, updates whether Coder identity headers are forwarded on every outgoing MCP request.     |
| `icon_url`              | string          | false    |              |                                                                                                                         |
| `model_intent`          | boolean         | false    |              |                                                                                                                         |
| `oauth2_auth_url`       | string          | false    |              |                                                                                                                         |
| `oauth2_client_id`      | string          | false    |              |                                                                                                                         |
| `oauth2_client_secret`  | string          | false    |              |                                                                                                                         |
| `oauth2_revocation_url` | string          | false    |              | Oauth2 revocation URL is validated in the handler because a validate tag would reject the pointer to "" that clears it. |
| `oauth2_scopes`         | string          | false    |              |                                                                                                                         |
| `oauth2_token_url`      | string          | false    |              |                                                                                                                         |
| `signing_secret`        | string          | false    |              | Signing secret replaces the shared signing key. Omit to preserve it; an empty string clears it. It is never returned.   |
| `slug`                  | string          | false    |              |                                                                                                                         |
| `tool_allow_list`       | array of string | false    |              |                                                                                                                         |
| `tool_deny_list`        | array of string | false    |              |                                                                                                                         |
| `transport`             | string          | false    |              |                                                                                                                         |
| `url`                   | string          | false    |              |                                                                                                                         |

#### Enumerated Values

| Property       | Value(s)                                                   |
|----------------|------------------------------------------------------------|
| `auth_type`    | `api_key`, `custom_headers`, `none`, `oauth2`, `user_oidc` |
| `availability` | `default_off`, `default_on`, `force_on`                    |
| `transport`    | `sse`, `streamable_http`                                   |

## codersdk.UpdateOrganizationRequest

```json
{
  "default_org_member_roles": [
    "string"
  ],
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "name": "string"
}
```

### Properties

| Name                       | Type            | Required | Restrictions | Description                                                                     |
|----------------------------|-----------------|----------|--------------|---------------------------------------------------------------------------------|
| `default_org_member_roles` | array of string | false    |              | Default org member roles when non-nil, replaces the org's default member roles. |
| `description`              | string          | false    |              |                                                                                 |
| `display_name`             | string          | false    |              |                                                                                 |
| `icon`                     | string          | false    |              |                                                                                 |
| `name`                     | string          | false    |              |                                                                                 |

## codersdk.UpdateRoles

```json
{
  "roles": [
    "string"
  ]
}
```

### Properties

| Name    | Type            | Required | Restrictions | Description |
|---------|-----------------|----------|--------------|-------------|
| `roles` | array of string | false    |              |             |

## codersdk.UpdateTemplateACL

```json
{
  "group_perms": {
    "8bd26b20-f3e8-48be-a903-46bb920cf671": "use",
    "<group_id>": "admin"
  },
  "user_perms": {
    "4df59e74-c027-470b-ab4d-cbba8963a5e9": "use",
    "<user_id>": "admin"
  }
}
```

### Properties

| Name               | Type                                           | Required | Restrictions | Description                                                                                                                                                                                                       |
|--------------------|------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `group_perms`      | object                                         | false    |              | Group perms is a mapping from valid group UUIDs to the template role they should be granted. To remove a group from the template, use "" as the role (available as a constant named codersdk.TemplateRoleDeleted) |
| » `[any property]` | [codersdk.TemplateRole](#codersdktemplaterole) | false    |              |                                                                                                                                                                                                                   |
| `user_perms`       | object                                         | false    |              | User perms is a mapping from valid user UUIDs to the template role they should be granted. To remove a user from the template, use "" as the role (available as a constant named codersdk.TemplateRoleDeleted)    |
| » `[any property]` | [codersdk.TemplateRole](#codersdktemplaterole) | false    |              |                                                                                                                                                                                                                   |

## codersdk.UpdateTemplateMeta

```json
{
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "cors_behavior": "simple",
  "default_ttl_ms": 0,
  "deprecation_message": "string",
  "description": "string",
  "disable_everyone_group_access": true,
  "disable_module_cache": true,
  "display_name": "string",
  "failure_ttl_ms": 0,
  "icon": "string",
  "max_port_share_level": "owner",
  "name": "string",
  "require_active_version": true,
  "time_til_autostop_notify_ms": 0,
  "time_til_dormant_autodelete_ms": 0,
  "time_til_dormant_ms": 0,
  "update_workspace_dormant_at": true,
  "update_workspace_last_used_at": true,
  "use_classic_parameter_flow": true
}
```

### Properties

| Name                               | Type                                                                           | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                                                        |
|------------------------------------|--------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `activity_bump_ms`                 | integer                                                                        | false    |              | Activity bump ms allows optionally specifying the activity bump duration for all workspaces created from this template. Defaults to 1h but can be set to 0 to disable activity bumping.                                                                                                                                                                                            |
| `agents_allowed`                   | boolean                                                                        | false    |              | Agents allowed controls whether Coder Agents can create workspaces using this template. If omitted, the current value is preserved.                                                                                                                                                                                                                                                |
| `allow_user_autostart`             | boolean                                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `allow_user_autostop`              | boolean                                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `allow_user_cancel_workspace_jobs` | boolean                                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `allow_workspace_renames`          | boolean                                                                        | false    |              | Allow workspace renames permits users to rename workspaces built from this template. Renaming can be destructive for templates whose Terraform references the workspace name.                                                                                                                                                                                                      |
| `autostart_requirement`            | [codersdk.TemplateAutostartRequirement](#codersdktemplateautostartrequirement) | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `autostop_requirement`             | [codersdk.TemplateAutostopRequirement](#codersdktemplateautostoprequirement)   | false    |              | Autostop requirement and AutostartRequirement can only be set if your license includes the advanced template scheduling feature. If you attempt to set this value while unlicensed, it will be ignored.                                                                                                                                                                            |
| `cors_behavior`                    | [codersdk.CORSBehavior](#codersdkcorsbehavior)                                 | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `default_ttl_ms`                   | integer                                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `deprecation_message`              | string                                                                         | false    |              | Deprecation message if set, will mark the template as deprecated and block any new workspaces from using this template. If passed an empty string, will remove the deprecated message, making the template usable for new workspaces again.                                                                                                                                        |
| `description`                      | string                                                                         | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `disable_everyone_group_access`    | boolean                                                                        | false    |              | Disable everyone group access allows optionally disabling the default behavior of granting the 'everyone' group access to use the template. If this is set to true, the template will not be available to all users, and must be explicitly granted to users or groups in the permissions settings of the template.                                                                |
| `disable_module_cache`             | boolean                                                                        | false    |              | Disable module cache disables the using of cached Terraform modules during provisioning. It is ignored while the deployment disables the module cache for all templates. It is recommended not to disable this.                                                                                                                                                                    |
| `display_name`                     | string                                                                         | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `failure_ttl_ms`                   | integer                                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `icon`                             | string                                                                         | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `max_port_share_level`             | [codersdk.WorkspaceAgentPortShareLevel](#codersdkworkspaceagentportsharelevel) | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `name`                             | string                                                                         | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `require_active_version`           | boolean                                                                        | false    |              | Require active version mandates workspaces built using this template use the active version of the template. This option has no effect on template admins.                                                                                                                                                                                                                         |
| `time_til_autostop_notify_ms`      | integer                                                                        | false    |              | Time til autostop notify ms allows optionally specifying the duration before the autostop deadline at which a reminder notification is sent for workspaces created from this template. Defaults to 0 (disabled). Omitting the field keeps the existing value.                                                                                                                      |
| `time_til_dormant_autodelete_ms`   | integer                                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `time_til_dormant_ms`              | integer                                                                        | false    |              |                                                                                                                                                                                                                                                                                                                                                                                    |
| `update_workspace_dormant_at`      | boolean                                                                        | false    |              | Update workspace dormant at updates the dormant_at field of workspaces spawned from the template. This is useful for preventing dormant workspaces being immediately deleted when updating the dormant_ttl field to a new, shorter value.                                                                                                                                          |
| `update_workspace_last_used_at`    | boolean                                                                        | false    |              | Update workspace last used at updates the last_used_at field of workspaces spawned from the template. This is useful for preventing workspaces being immediately locked when updating the inactivity_ttl field to a new, shorter value.                                                                                                                                            |
| `use_classic_parameter_flow`       | boolean                                                                        | false    |              | Use classic parameter flow is a flag that switches the default behavior to use the classic parameter flow when creating a workspace. This only affects deployments with the experiment "dynamic-parameters" enabled. This setting will live for a period after the experiment is made the default. An "opt-out" is present in case the new feature breaks some existing templates. |

## codersdk.UpdateUserAppearanceSettingsRequest

```json
{
  "terminal_font": "",
  "theme_dark": "light",
  "theme_light": "light",
  "theme_mode": "sync",
  "theme_preference": "string"
}
```

### Properties

| Name               | Type                                                   | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                        |
|--------------------|--------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `terminal_font`    | [codersdk.TerminalFontName](#codersdkterminalfontname) | true     |              |                                                                                                                                                                                                                                                                                                                    |
| `theme_dark`       | string                                                 | false    |              | Theme dark is required when ThemeMode is "sync". In "single" mode an empty value means "preserve the previously persisted slot" rather than "clear the slot", so partial updates that send only one slot keep the other intact.                                                                                    |
| `theme_light`      | string                                                 | false    |              | Theme light is required when ThemeMode is "sync". In "single" mode an empty value means "preserve the previously persisted slot" rather than "clear the slot", so partial updates that send only one slot keep the other intact.                                                                                   |
| `theme_mode`       | [codersdk.ThemeMode](#codersdkthememode)               | false    |              | Theme mode is optional for backward compatibility. When empty, the server leaves theme_mode, theme_light, and theme_dark unchanged so older CLI clients do not erase sync-mode settings. Legacy auto preferences are the exception: they clear theme_mode so clients can migrate the old sync-with-system setting. |
| `theme_preference` | string                                                 | true     |              |                                                                                                                                                                                                                                                                                                                    |

#### Enumerated Values

| Property      | Value(s)                                                                                    |
|---------------|---------------------------------------------------------------------------------------------|
| `theme_dark`  | `dark`, `dark-protan-deuter`, `dark-tritan`, `light`, `light-protan-deuter`, `light-tritan` |
| `theme_light` | `dark`, `dark-protan-deuter`, `dark-tritan`, `light`, `light-protan-deuter`, `light-tritan` |
| `theme_mode`  | `single`, `sync`                                                                            |

## codersdk.UpdateUserChatCompactionThresholdRequest

```json
{
  "threshold_percent": 100
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `threshold_percent` | integer | false    |              |             |

## codersdk.UpdateUserChatDebugLoggingRequest

```json
{
  "debug_logging_enabled": true
}
```

### Properties

| Name                    | Type    | Required | Restrictions | Description |
|-------------------------|---------|----------|--------------|-------------|
| `debug_logging_enabled` | boolean | false    |              |             |

## codersdk.UpdateUserChatPersonalModelOverrideRequest

```json
{
  "mode": "deployment_default",
  "model_config_id": "string",
  "reasoning_effort": "string"
}
```

### Properties

| Name               | Type                                                                             | Required | Restrictions | Description |
|--------------------|----------------------------------------------------------------------------------|----------|--------------|-------------|
| `mode`             | [codersdk.ChatPersonalModelOverrideMode](#codersdkchatpersonalmodeloverridemode) | false    |              |             |
| `model_config_id`  | string                                                                           | false    |              |             |
| `reasoning_effort` | string                                                                           | false    |              |             |

## codersdk.UpdateUserEmailRequest

```json
{
  "new_email": "user@example.com",
  "old_email": "user@example.com"
}
```

### Properties

| Name        | Type   | Required | Restrictions | Description |
|-------------|--------|----------|--------------|-------------|
| `new_email` | string | true     |              |             |
| `old_email` | string | true     |              |             |

## codersdk.UpdateUserNotificationPreferences

```json
{
  "template_disabled_map": {
    "property1": true,
    "property2": true
  }
}
```

### Properties

| Name                    | Type    | Required | Restrictions | Description |
|-------------------------|---------|----------|--------------|-------------|
| `template_disabled_map` | object  | false    |              |             |
| » `[any property]`      | boolean | false    |              |             |

## codersdk.UpdateUserPasswordRequest

```json
{
  "old_password": "string",
  "password": "string"
}
```

### Properties

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `old_password` | string | false    |              |             |
| `password`     | string | true     |              |             |

## codersdk.UpdateUserPreferenceSettingsRequest

```json
{
  "agent_chat_send_shortcut": "enter",
  "code_diff_display_mode": "auto",
  "collapse_assistant_steps": true,
  "shell_tool_display_mode": "auto",
  "thinking_display_mode": "auto"
}
```

### Properties

| Name                       | Type                                                             | Required | Restrictions | Description |
|----------------------------|------------------------------------------------------------------|----------|--------------|-------------|
| `agent_chat_send_shortcut` | [codersdk.AgentChatSendShortcut](#codersdkagentchatsendshortcut) | false    |              |             |
| `code_diff_display_mode`   | [codersdk.AgentDisplayMode](#codersdkagentdisplaymode)           | false    |              |             |
| `collapse_assistant_steps` | boolean                                                          | false    |              |             |
| `shell_tool_display_mode`  | [codersdk.AgentDisplayMode](#codersdkagentdisplaymode)           | false    |              |             |
| `thinking_display_mode`    | [codersdk.ThinkingDisplayMode](#codersdkthinkingdisplaymode)     | false    |              |             |

## codersdk.UpdateUserProfileRequest

```json
{
  "avatar_url": "http://example.com",
  "name": "string",
  "username": "string"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description                                                                                                                                                                                 |
|--------------|--------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `avatar_url` | string | false    |              | Avatar URL is only applied for users whose login type is password or none. For other login types the avatar is synced from the identity provider on login, so a submitted value is ignored. |
| `name`       | string | false    |              |                                                                                                                                                                                             |
| `username`   | string | true     |              |                                                                                                                                                                                             |

## codersdk.UpdateUserQuietHoursScheduleRequest

```json
{
  "schedule": "string"
}
```

### Properties

|Name|Type|Required|Restrictions|Description|
|---|---|---|---|---|
|`schedule`|string|true||Schedule is a cron expression that defines when the user's quiet hours window is. Schedule must not be empty. For new users, the schedule is set to 2am in their browser or computer's timezone. The schedule denotes the beginning of a 4 hour window where the workspace is allowed to automatically stop or restart due to maintenance or template schedule.
The schedule must be daily with a single time, and should have a timezone specified via a CRON_TZ prefix (otherwise UTC will be used).
If the schedule is empty, the user will be updated to use the default schedule.|

## codersdk.UpdateUserSecretRequest

```json
{
  "description": "string",
  "enabled": true,
  "env_name": "string",
  "file_path": "string",
  "value": "string"
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description |
|---------------|---------|----------|--------------|-------------|
| `description` | string  | false    |              |             |
| `enabled`     | boolean | false    |              |             |
| `env_name`    | string  | false    |              |             |
| `file_path`   | string  | false    |              |             |
| `value`       | string  | false    |              |             |

## codersdk.UpdateUserSkillRequest

```json
{
  "content": "string"
}
```

### Properties

| Name      | Type   | Required | Restrictions | Description                                                                                                                                                           |
|-----------|--------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `content` | string | false    |              | Content must be SKILL.md-format Markdown with YAML frontmatter. The frontmatter must include name, may include description, and must be followed by a non-empty body. |

## codersdk.UpdateWorkspaceACL

```json
{
  "group_roles": {
    "property1": "admin",
    "property2": "admin"
  },
  "user_roles": {
    "property1": "admin",
    "property2": "admin"
  }
}
```

### Properties

| Name               | Type                                             | Required | Restrictions | Description                                                                                                                                                                                                          |
|--------------------|--------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `group_roles`      | object                                           | false    |              | Group roles is a mapping from valid group UUIDs to the workspace role they should be granted. To remove a group from the workspace, use "" as the role (available as a constant named codersdk.WorkspaceRoleDeleted) |
| » `[any property]` | [codersdk.WorkspaceRole](#codersdkworkspacerole) | false    |              |                                                                                                                                                                                                                      |
| `user_roles`       | object                                           | false    |              | User roles is a mapping from valid user UUIDs to the workspace role they should be granted. To remove a user from the workspace, use "" as the role (available as a constant named codersdk.WorkspaceRoleDeleted)    |
| » `[any property]` | [codersdk.WorkspaceRole](#codersdkworkspacerole) | false    |              |                                                                                                                                                                                                                      |

## codersdk.UpdateWorkspaceAutomaticUpdatesRequest

```json
{
  "automatic_updates": "always"
}
```

### Properties

| Name                | Type                                                   | Required | Restrictions | Description |
|---------------------|--------------------------------------------------------|----------|--------------|-------------|
| `automatic_updates` | [codersdk.AutomaticUpdates](#codersdkautomaticupdates) | false    |              |             |

## codersdk.UpdateWorkspaceAutostartRequest

```json
{
  "schedule": "string"
}
```

### Properties

| Name       | Type   | Required | Restrictions | Description                                                                                                                                                                                                                                    |
|------------|--------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `schedule` | string | false    |              | Schedule is expected to be of the form `CRON_TZ=<IANA Timezone> <min> <hour> * * <dow>` Example: `CRON_TZ=US/Central 30 9 * * 1-5` represents 0930 in the timezone US/Central on weekdays (Mon-Fri). `CRON_TZ` defaults to UTC if not present. |

## codersdk.UpdateWorkspaceBuildStateRequest

```json
{
  "state": [
    0
  ]
}
```

### Properties

| Name    | Type             | Required | Restrictions | Description |
|---------|------------------|----------|--------------|-------------|
| `state` | array of integer | false    |              |             |

## codersdk.UpdateWorkspaceDormancy

```json
{
  "dormant": true
}
```

### Properties

| Name      | Type    | Required | Restrictions | Description |
|-----------|---------|----------|--------------|-------------|
| `dormant` | boolean | false    |              |             |

## codersdk.UpdateWorkspaceRequest

```json
{
  "name": "string"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description |
|--------|--------|----------|--------------|-------------|
| `name` | string | false    |              |             |

## codersdk.UpdateWorkspaceSharingSettingsRequest

```json
{
  "shareable_workspace_owners": "none",
  "sharing_disabled": true
}
```

### Properties

| Name                         | Type                                                                   | Required | Restrictions | Description                                                                                                                     |
|------------------------------|------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------|
| `shareable_workspace_owners` | [codersdk.ShareableWorkspaceOwners](#codersdkshareableworkspaceowners) | false    |              | Shareable workspace owners controls whose workspaces can be shared within the organization.                                     |
| `sharing_disabled`           | boolean                                                                | false    |              | Sharing disabled is deprecated and left for backward compatibility purposes. Deprecated: use `ShareableWorkspaceOwners` instead |

#### Enumerated Values

| Property                     | Value(s)                               |
|------------------------------|----------------------------------------|
| `shareable_workspace_owners` | `everyone`, `none`, `service_accounts` |

## codersdk.UpdateWorkspaceTTLRequest

```json
{
  "ttl_ms": 0
}
```

### Properties

| Name     | Type    | Required | Restrictions | Description |
|----------|---------|----------|--------------|-------------|
| `ttl_ms` | integer | false    |              |             |

## codersdk.UploadChatFileResponse

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}
```

### Properties

| Name | Type   | Required | Restrictions | Description |
|------|--------|----------|--------------|-------------|
| `id` | string | false    |              |             |

## codersdk.UploadChatWorkspaceFileResponse

```json
{
  "media_type": "string",
  "name": "string",
  "path": "string",
  "size": 0,
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Properties

| Name           | Type    | Required | Restrictions | Description                                                                                                             |
|----------------|---------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------|
| `media_type`   | string  | false    |              | Media type is the client-declared content type for display.                                                             |
| `name`         | string  | false    |              | Name is the final basename of the uploaded file.                                                                        |
| `path`         | string  | false    |              | Path is the absolute path of the file on the workspace.                                                                 |
| `size`         | integer | false    |              | Size is the number of bytes written to the workspace.                                                                   |
| `workspace_id` | string  | false    |              | Workspace ID is the workspace whose filesystem received the bytes. Message parts referencing this upload must carry it. |

## codersdk.UploadResponse

```json
{
  "hash": "19686d84-b10d-4f90-b18e-84fd3fa038fd"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description |
|--------|--------|----------|--------------|-------------|
| `hash` | string | false    |              |             |

## codersdk.UpsertAIModelPricesRequest

```json
{
  "prices": [
    {
      "cache_read_price": 0,
      "cache_write_price": 0,
      "input_price": 0,
      "model": "string",
      "output_price": 0,
      "provider": "string"
    }
  ]
}
```

### Properties

| Name     | Type                                                                | Required | Restrictions | Description |
|----------|---------------------------------------------------------------------|----------|--------------|-------------|
| `prices` | array of [codersdk.AIModelPriceUpsert](#codersdkaimodelpriceupsert) | false    |              |             |

## codersdk.UpsertGroupAIBudgetRequest

```json
{
  "spend_limit_micros": 0
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description                                               |
|----------------------|---------|----------|--------------|-----------------------------------------------------------|
| `spend_limit_micros` | integer | false    |              | Spend limit micros must not exceed MaxAISpendLimitMicros. |

## codersdk.UpsertUserAIBudgetOverrideRequest

```json
{
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description                                                                                       |
|----------------------|---------|----------|--------------|---------------------------------------------------------------------------------------------------|
| `group_id`           | string  | true     |              | Group ID is the group the user's spend is attributed to. The user must be a member of this group. |
| `spend_limit_micros` | integer | false    |              | Spend limit micros must not exceed MaxAISpendLimitMicros.                                         |

## codersdk.UpsertWorkspaceAgentPortShareRequest

```json
{
  "agent_name": "string",
  "port": 0,
  "protocol": "http",
  "share_level": "owner"
}
```

### Properties

| Name          | Type                                                                                 | Required | Restrictions | Description |
|---------------|--------------------------------------------------------------------------------------|----------|--------------|-------------|
| `agent_name`  | string                                                                               | false    |              |             |
| `port`        | integer                                                                              | false    |              |             |
| `protocol`    | [codersdk.WorkspaceAgentPortShareProtocol](#codersdkworkspaceagentportshareprotocol) | false    |              |             |
| `share_level` | [codersdk.WorkspaceAgentPortShareLevel](#codersdkworkspaceagentportsharelevel)       | false    |              |             |

#### Enumerated Values

| Property      | Value(s)                                           |
|---------------|----------------------------------------------------|
| `protocol`    | `http`, `https`                                    |
| `share_level` | `authenticated`, `organization`, `owner`, `public` |

## codersdk.UsagePeriod

```json
{
  "end": "2019-08-24T14:15:22Z",
  "issued_at": "2019-08-24T14:15:22Z",
  "start": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name        | Type   | Required | Restrictions | Description |
|-------------|--------|----------|--------------|-------------|
| `end`       | string | false    |              |             |
| `issued_at` | string | false    |              |             |
| `start`     | string | false    |              |             |

## codersdk.UsageStatsConfig

```json
{
  "enable": true
}
```

### Properties

| Name     | Type    | Required | Restrictions | Description |
|----------|---------|----------|--------------|-------------|
| `enable` | boolean | false    |              |             |

## codersdk.User

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Properties

| Name                 | Type                                            | Required | Restrictions | Description                                                                                      |
|----------------------|-------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------|
| `avatar_url`         | string                                          | false    |              |                                                                                                  |
| `created_at`         | string                                          | true     |              |                                                                                                  |
| `email`              | string                                          | true     |              |                                                                                                  |
| `has_ai_seat`        | boolean                                         | false    |              | Has ai seat intentionally omits omitempty so the API always includes the field, even when false. |
| `id`                 | string                                          | true     |              |                                                                                                  |
| `is_service_account` | boolean                                         | false    |              |                                                                                                  |
| `last_seen_at`       | string                                          | false    |              |                                                                                                  |
| `login_type`         | [codersdk.LoginType](#codersdklogintype)        | false    |              |                                                                                                  |
| `name`               | string                                          | false    |              |                                                                                                  |
| `organization_ids`   | array of string                                 | false    |              |                                                                                                  |
| `roles`              | array of [codersdk.SlimRole](#codersdkslimrole) | false    |              |                                                                                                  |
| `status`             | [codersdk.UserStatus](#codersdkuserstatus)      | false    |              |                                                                                                  |
| `theme_preference`   | string                                          | false    |              | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead.       |
| `updated_at`         | string                                          | false    |              |                                                                                                  |
| `username`           | string                                          | true     |              |                                                                                                  |

#### Enumerated Values

| Property | Value(s)              |
|----------|-----------------------|
| `status` | `active`, `suspended` |

## codersdk.UserAIBudgetOverride

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "group_id": "306db4e0-7449-4501-b76f-075576fe2d8f",
  "spend_limit_micros": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `created_at`         | string  | false    |              |             |
| `group_id`           | string  | false    |              |             |
| `spend_limit_micros` | integer | false    |              |             |
| `updated_at`         | string  | false    |              |             |
| `user_id`            | string  | false    |              |             |

## codersdk.UserAIProviderKeyConfig

```json
{
  "byok_enabled": true,
  "has_provider_api_key": true,
  "has_user_api_key": true,
  "provider": {
    "deleted": true,
    "display_name": "string",
    "enabled": true,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "type": "openai"
  }
}
```

### Properties

| Name                   | Type                                                     | Required | Restrictions | Description |
|------------------------|----------------------------------------------------------|----------|--------------|-------------|
| `byok_enabled`         | boolean                                                  | false    |              |             |
| `has_provider_api_key` | boolean                                                  | false    |              |             |
| `has_user_api_key`     | boolean                                                  | false    |              |             |
| `provider`             | [codersdk.AIProviderSummary](#codersdkaiprovidersummary) | false    |              |             |

## codersdk.UserAISpendStatus

```json
{
  "current_spend_micros": 0,
  "effective_budget": {
    "limit_source": "user_override",
    "spend_limit_micros": 0
  },
  "effective_group_id": "85e2b926-ddfb-4c66-b68e-b66e5acec6c0",
  "period_end": "2019-08-24T14:15:22Z",
  "period_start": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Properties

| Name                   | Type                                             | Required | Restrictions | Description                                                                                                                                                                            |
|------------------------|--------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `current_spend_micros` | integer                                          | false    |              | Current spend micros is the user's spend on their effective group over the current budget period.                                                                                      |
| `effective_budget`     | [codersdk.AIBudgetLimit](#codersdkaibudgetlimit) | false    |              | Effective budget is the spend limit that applies to the user, whether it came from a group budget or a user override. Null when no budget applies, leaving the user's spend unlimited. |
| `effective_group_id`   | string                                           | false    |              | Effective group ID is the group the spend is attributed to, falling back to the Everyone group when no budget applies. Null only when the user has no organization membership.         |
| `period_end`           | string                                           | false    |              | Period end is the exclusive upper bound of the current budget period.                                                                                                                  |
| `period_start`         | string                                           | false    |              | Period start is the inclusive lower bound of the current budget period.                                                                                                                |
| `user_id`              | string                                           | false    |              |                                                                                                                                                                                        |

## codersdk.UserActivity

```json
{
  "avatar_url": "http://example.com",
  "seconds": 80500,
  "template_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  "username": "string"
}
```

### Properties

| Name           | Type            | Required | Restrictions | Description |
|----------------|-----------------|----------|--------------|-------------|
| `avatar_url`   | string          | false    |              |             |
| `seconds`      | integer         | false    |              |             |
| `template_ids` | array of string | false    |              |             |
| `user_id`      | string          | false    |              |             |
| `username`     | string          | false    |              |             |

## codersdk.UserActivityInsightsReport

```json
{
  "end_time": "2019-08-24T14:15:22Z",
  "start_time": "2019-08-24T14:15:22Z",
  "template_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "seconds": 80500,
      "template_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
      "username": "string"
    }
  ]
}
```

### Properties

| Name           | Type                                                    | Required | Restrictions | Description |
|----------------|---------------------------------------------------------|----------|--------------|-------------|
| `end_time`     | string                                                  | false    |              |             |
| `start_time`   | string                                                  | false    |              |             |
| `template_ids` | array of string                                         | false    |              |             |
| `users`        | array of [codersdk.UserActivity](#codersdkuseractivity) | false    |              |             |

## codersdk.UserActivityInsightsResponse

```json
{
  "report": {
    "end_time": "2019-08-24T14:15:22Z",
    "start_time": "2019-08-24T14:15:22Z",
    "template_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "users": [
      {
        "avatar_url": "http://example.com",
        "seconds": 80500,
        "template_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
        "username": "string"
      }
    ]
  }
}
```

### Properties

| Name     | Type                                                                       | Required | Restrictions | Description |
|----------|----------------------------------------------------------------------------|----------|--------------|-------------|
| `report` | [codersdk.UserActivityInsightsReport](#codersdkuseractivityinsightsreport) | false    |              |             |

## codersdk.UserAppearanceSettings

```json
{
  "terminal_font": "",
  "theme_dark": "string",
  "theme_light": "string",
  "theme_mode": "",
  "theme_preference": "string"
}
```

### Properties

| Name               | Type                                                   | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                               |
|--------------------|--------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `terminal_font`    | [codersdk.TerminalFontName](#codersdkterminalfontname) | false    |              |                                                                                                                                                                                                                                                                                                                                           |
| `theme_dark`       | string                                                 | false    |              | Ignored when ThemeMode is "single"                                                                                                                                                                                                                                                                                                        |
| `theme_light`      | string                                                 | false    |              | Ignored when ThemeMode is "single"                                                                                                                                                                                                                                                                                                        |
| `theme_mode`       | [codersdk.ThemeMode](#codersdkthememode)               | false    |              |                                                                                                                                                                                                                                                                                                                                           |
| `theme_preference` | string                                                 | false    |              | Theme preference is the legacy single-field appearance setting. In "single" mode it mirrors the active theme. In "sync" mode modern clients normally mirror the active OS slot, but older clients can update only this field, so it may diverge from ThemeLight or ThemeDark until a modern client saves the full appearance state again. |

## codersdk.UserChatCompactionThreshold

```json
{
  "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
  "threshold_percent": 0
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `model_config_id`   | string  | false    |              |             |
| `threshold_percent` | integer | false    |              |             |

## codersdk.UserChatCompactionThresholds

```json
{
  "thresholds": [
    {
      "model_config_id": "f5fb4d91-62ca-4377-9ee6-5d43ba00d205",
      "threshold_percent": 0
    }
  ]
}
```

### Properties

| Name         | Type                                                                                  | Required | Restrictions | Description |
|--------------|---------------------------------------------------------------------------------------|----------|--------------|-------------|
| `thresholds` | array of [codersdk.UserChatCompactionThreshold](#codersdkuserchatcompactionthreshold) | false    |              |             |

## codersdk.UserChatCustomPrompt

```json
{
  "custom_prompt": "string"
}
```

### Properties

| Name            | Type   | Required | Restrictions | Description |
|-----------------|--------|----------|--------------|-------------|
| `custom_prompt` | string | false    |              |             |

## codersdk.UserChatDebugLoggingSettings

```json
{
  "debug_logging_enabled": true,
  "forced_by_deployment": true,
  "user_toggle_allowed": true
}
```

### Properties

| Name                    | Type    | Required | Restrictions | Description |
|-------------------------|---------|----------|--------------|-------------|
| `debug_logging_enabled` | boolean | false    |              |             |
| `forced_by_deployment`  | boolean | false    |              |             |
| `user_toggle_allowed`   | boolean | false    |              |             |

## codersdk.UserChatPersonalModelOverridesResponse

```json
{
  "deployment_defaults": {
    "explore": {
      "context": "general",
      "model_config_id": "string",
      "reasoning_effort": "string"
    },
    "general": {
      "context": "general",
      "model_config_id": "string",
      "reasoning_effort": "string"
    }
  },
  "enabled": true,
  "explore": {
    "context": "root",
    "is_set": true,
    "mode": "deployment_default",
    "model_config_id": "string",
    "reasoning_effort": "string"
  },
  "general": {
    "context": "root",
    "is_set": true,
    "mode": "deployment_default",
    "model_config_id": "string",
    "reasoning_effort": "string"
  },
  "root": {
    "context": "root",
    "is_set": true,
    "mode": "deployment_default",
    "model_config_id": "string",
    "reasoning_effort": "string"
  }
}
```

### Properties

| Name                  | Type                                                                                                         | Required | Restrictions | Description |
|-----------------------|--------------------------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `deployment_defaults` | [codersdk.ChatPersonalModelOverrideDeploymentDefaults](#codersdkchatpersonalmodeloverridedeploymentdefaults) | false    |              |             |
| `enabled`             | boolean                                                                                                      | false    |              |             |
| `explore`             | [codersdk.ChatPersonalModelOverride](#codersdkchatpersonalmodeloverride)                                     | false    |              |             |
| `general`             | [codersdk.ChatPersonalModelOverride](#codersdkchatpersonalmodeloverride)                                     | false    |              |             |
| `root`                | [codersdk.ChatPersonalModelOverride](#codersdkchatpersonalmodeloverride)                                     | false    |              |             |

## codersdk.UserLatency

```json
{
  "avatar_url": "http://example.com",
  "latency_ms": {
    "p50": 31.312,
    "p95": 119.832
  },
  "template_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
  "username": "string"
}
```

### Properties

| Name           | Type                                                     | Required | Restrictions | Description |
|----------------|----------------------------------------------------------|----------|--------------|-------------|
| `avatar_url`   | string                                                   | false    |              |             |
| `latency_ms`   | [codersdk.ConnectionLatency](#codersdkconnectionlatency) | false    |              |             |
| `template_ids` | array of string                                          | false    |              |             |
| `user_id`      | string                                                   | false    |              |             |
| `username`     | string                                                   | false    |              |             |

## codersdk.UserLatencyInsightsReport

```json
{
  "end_time": "2019-08-24T14:15:22Z",
  "start_time": "2019-08-24T14:15:22Z",
  "template_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "latency_ms": {
        "p50": 31.312,
        "p95": 119.832
      },
      "template_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
      "username": "string"
    }
  ]
}
```

### Properties

| Name           | Type                                                  | Required | Restrictions | Description |
|----------------|-------------------------------------------------------|----------|--------------|-------------|
| `end_time`     | string                                                | false    |              |             |
| `start_time`   | string                                                | false    |              |             |
| `template_ids` | array of string                                       | false    |              |             |
| `users`        | array of [codersdk.UserLatency](#codersdkuserlatency) | false    |              |             |

## codersdk.UserLatencyInsightsResponse

```json
{
  "report": {
    "end_time": "2019-08-24T14:15:22Z",
    "start_time": "2019-08-24T14:15:22Z",
    "template_ids": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "users": [
      {
        "avatar_url": "http://example.com",
        "latency_ms": {
          "p50": 31.312,
          "p95": 119.832
        },
        "template_ids": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5",
        "username": "string"
      }
    ]
  }
}
```

### Properties

| Name     | Type                                                                     | Required | Restrictions | Description |
|----------|--------------------------------------------------------------------------|----------|--------------|-------------|
| `report` | [codersdk.UserLatencyInsightsReport](#codersdkuserlatencyinsightsreport) | false    |              |             |

## codersdk.UserLoginType

```json
{
  "login_type": ""
}
```

### Properties

| Name         | Type                                     | Required | Restrictions | Description |
|--------------|------------------------------------------|----------|--------------|-------------|
| `login_type` | [codersdk.LoginType](#codersdklogintype) | false    |              |             |

## codersdk.UserParameter

```json
{
  "name": "string",
  "value": "string"
}
```

### Properties

| Name    | Type   | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `name`  | string | false    |              |             |
| `value` | string | false    |              |             |

## codersdk.UserPreferenceSettings

```json
{
  "agent_chat_send_shortcut": "enter",
  "code_diff_display_mode": "auto",
  "collapse_assistant_steps": true,
  "shell_tool_display_mode": "auto",
  "thinking_display_mode": "auto"
}
```

### Properties

| Name                       | Type                                                             | Required | Restrictions | Description |
|----------------------------|------------------------------------------------------------------|----------|--------------|-------------|
| `agent_chat_send_shortcut` | [codersdk.AgentChatSendShortcut](#codersdkagentchatsendshortcut) | false    |              |             |
| `code_diff_display_mode`   | [codersdk.AgentDisplayMode](#codersdkagentdisplaymode)           | false    |              |             |
| `collapse_assistant_steps` | boolean                                                          | false    |              |             |
| `shell_tool_display_mode`  | [codersdk.AgentDisplayMode](#codersdkagentdisplaymode)           | false    |              |             |
| `thinking_display_mode`    | [codersdk.ThinkingDisplayMode](#codersdkthinkingdisplaymode)     | false    |              |             |

## codersdk.UserQuietHoursScheduleConfig

```json
{
  "allow_user_custom": true,
  "default_schedule": "string"
}
```

### Properties

| Name                | Type    | Required | Restrictions | Description |
|---------------------|---------|----------|--------------|-------------|
| `allow_user_custom` | boolean | false    |              |             |
| `default_schedule`  | string  | false    |              |             |

## codersdk.UserQuietHoursScheduleResponse

```json
{
  "next": "2019-08-24T14:15:22Z",
  "raw_schedule": "string",
  "time": "string",
  "timezone": "string",
  "user_can_set": true,
  "user_set": true
}
```

### Properties

| Name           | Type    | Required | Restrictions | Description                                                                                                                                                                      |
|----------------|---------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `next`         | string  | false    |              | Next is the next time that the quiet hours window will start.                                                                                                                    |
| `raw_schedule` | string  | false    |              |                                                                                                                                                                                  |
| `time`         | string  | false    |              | Time is the time of day that the quiet hours window starts in the given Timezone each day.                                                                                       |
| `timezone`     | string  | false    |              | raw format from the cron expression, UTC if unspecified                                                                                                                          |
| `user_can_set` | boolean | false    |              | User can set is true if the user is allowed to set their own quiet hours schedule. If false, the user cannot set a custom schedule and the default schedule will always be used. |
| `user_set`     | boolean | false    |              | User set is true if the user has set their own quiet hours schedule. If false, the user is using the default schedule.                                                           |

## codersdk.UserSecret

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "description": "string",
  "enabled": true,
  "env_name": "string",
  "file_path": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name          | Type    | Required | Restrictions | Description                                                                                                                                                                                                                          |
|---------------|---------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `created_at`  | string  | false    |              |                                                                                                                                                                                                                                      |
| `description` | string  | false    |              |                                                                                                                                                                                                                                      |
| `enabled`     | boolean | false    |              | Enabled controls whether the secret is injected into workspaces. Disabled secrets remain visible and editable, but are not added to the agent manifest, so they are not exposed as environment variables or written to secret files. |
| `env_name`    | string  | false    |              |                                                                                                                                                                                                                                      |
| `file_path`   | string  | false    |              |                                                                                                                                                                                                                                      |
| `id`          | string  | false    |              |                                                                                                                                                                                                                                      |
| `name`        | string  | false    |              |                                                                                                                                                                                                                                      |
| `updated_at`  | string  | false    |              |                                                                                                                                                                                                                                      |

## codersdk.UserSecretsCapabilities

```json
{
  "file_path_delivery_enabled": true
}
```

### Properties

| Name                         | Type    | Required | Restrictions | Description                                                                                                                       |
|------------------------------|---------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------|
| `file_path_delivery_enabled` | boolean | false    |              | File path delivery enabled reports whether Coder writes stored file paths into workspaces. Stored paths are preserved either way. |

## codersdk.UserSkill

```json
{
  "content": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "description": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name          | Type   | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `content`     | string | false    |              |             |
| `created_at`  | string | false    |              |             |
| `description` | string | false    |              |             |
| `id`          | string | false    |              |             |
| `name`        | string | false    |              |             |
| `updated_at`  | string | false    |              |             |

## codersdk.UserSkillMetadata

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "description": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name          | Type   | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `created_at`  | string | false    |              |             |
| `description` | string | false    |              |             |
| `id`          | string | false    |              |             |
| `name`        | string | false    |              |             |
| `updated_at`  | string | false    |              |             |

## codersdk.UserStatus

```json
"active"
```

### Properties

#### Enumerated Values

| Value(s)                         |
|----------------------------------|
| `active`, `dormant`, `suspended` |

## codersdk.UserStatusChangeCount

```json
{
  "count": 10,
  "date": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name    | Type    | Required | Restrictions | Description |
|---------|---------|----------|--------------|-------------|
| `count` | integer | false    |              |             |
| `date`  | string  | false    |              |             |

## codersdk.ValidateUserPasswordRequest

```json
{
  "password": "string"
}
```

### Properties

| Name       | Type   | Required | Restrictions | Description |
|------------|--------|----------|--------------|-------------|
| `password` | string | true     |              |             |

## codersdk.ValidateUserPasswordResponse

```json
{
  "details": "string",
  "valid": true
}
```

### Properties

| Name      | Type    | Required | Restrictions | Description |
|-----------|---------|----------|--------------|-------------|
| `details` | string  | false    |              |             |
| `valid`   | boolean | false    |              |             |

## codersdk.ValidationError

```json
{
  "detail": "string",
  "field": "string"
}
```

### Properties

| Name     | Type   | Required | Restrictions | Description |
|----------|--------|----------|--------------|-------------|
| `detail` | string | true     |              |             |
| `field`  | string | true     |              |             |

## codersdk.ValidationMonotonicOrder

```json
"increasing"
```

### Properties

#### Enumerated Values

| Value(s)                   |
|----------------------------|
| `decreasing`, `increasing` |

## codersdk.VariableValue

```json
{
  "name": "string",
  "value": "string"
}
```

### Properties

| Name    | Type   | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `name`  | string | false    |              |             |
| `value` | string | false    |              |             |

## codersdk.WebpushSubscription

```json
{
  "auth_key": "string",
  "endpoint": "string",
  "p256dh_key": "string"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description |
|--------------|--------|----------|--------------|-------------|
| `auth_key`   | string | false    |              |             |
| `endpoint`   | string | false    |              |             |
| `p256dh_key` | string | false    |              |             |

## codersdk.Workspace

```json
{
  "allow_renames": true,
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "deleting_at": "2019-08-24T14:15:22Z",
  "dormant_at": "2019-08-24T14:15:22Z",
  "favorite": true,
  "health": {
    "failing_agents": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "healthy": false
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_prebuild": true,
  "last_used_at": "2019-08-24T14:15:22Z",
  "latest_app_status": {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
    "created_at": "2019-08-24T14:15:22Z",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "message": "string",
    "needs_user_attention": true,
    "state": "working",
    "uri": "string",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  },
  "latest_build": {
    "build_number": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "deadline": "2019-08-24T14:15:22Z",
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "initiator_name": "string",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "max_deadline": "2019-08-24T14:15:22Z",
    "reason": "initiator",
    "resources": [
      {
        "agents": [
          {
            "api_version": "string",
            "apps": [
              {
                "command": "string",
                "display_name": "string",
                "external": true,
                "group": "string",
                "health": "disabled",
                "healthcheck": {
                  "interval": 0,
                  "threshold": 0,
                  "url": "string"
                },
                "hidden": true,
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "open_in": "slim-window",
                "sharing_level": "owner",
                "slug": "string",
                "statuses": [
                  {
                    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                    "created_at": "2019-08-24T14:15:22Z",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "message": "string",
                    "needs_user_attention": true,
                    "state": "working",
                    "uri": "string",
                    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                  }
                ],
                "subdomain": true,
                "subdomain_name": "string",
                "tooltip": "string",
                "url": "string"
              }
            ],
            "architecture": "string",
            "connection_timeout_seconds": 0,
            "created_at": "2019-08-24T14:15:22Z",
            "directory": "string",
            "disconnected_at": "2019-08-24T14:15:22Z",
            "display_apps": [
              "vscode"
            ],
            "environment_variables": {
              "property1": "string",
              "property2": "string"
            },
            "expanded_directory": "string",
            "first_connected_at": "2019-08-24T14:15:22Z",
            "health": {
              "healthy": false,
              "reason": "agent has lost connection"
            },
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "instance_id": "string",
            "last_connected_at": "2019-08-24T14:15:22Z",
            "latency": {
              "property1": {
                "latency_ms": 0,
                "preferred": true
              },
              "property2": {
                "latency_ms": 0,
                "preferred": true
              }
            },
            "lifecycle_state": "created",
            "log_sources": [
              {
                "created_at": "2019-08-24T14:15:22Z",
                "display_name": "string",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
              }
            ],
            "logs_length": 0,
            "logs_overflowed": true,
            "metadata": [
              {
                "description": {
                  "display_name": "string",
                  "interval": 0,
                  "key": "string",
                  "script": "string",
                  "timeout": 0
                },
                "result": {
                  "age": 0,
                  "collected_at": "2019-08-24T14:15:22Z",
                  "error": "string",
                  "value": "string"
                }
              }
            ],
            "name": "string",
            "operating_system": "string",
            "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
            "ready_at": "2019-08-24T14:15:22Z",
            "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
            "scripts": [
              {
                "cron": "string",
                "display_name": "string",
                "exit_code": 0,
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "log_path": "string",
                "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                "run_on_start": true,
                "run_on_stop": true,
                "script": "string",
                "start_blocks_login": true,
                "status": "ok",
                "timeout": 0
              }
            ],
            "started_at": "2019-08-24T14:15:22Z",
            "startup_script_behavior": "blocking",
            "status": "connecting",
            "subsystems": [
              "envbox"
            ],
            "troubleshooting_url": "string",
            "updated_at": "2019-08-24T14:15:22Z",
            "version": "string"
          }
        ],
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "hide": true,
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
        "metadata": [
          {
            "key": "string",
            "sensitive": true,
            "value": "string"
          }
        ],
        "name": "string",
        "type": "string",
        "workspace_transition": "start"
      }
    ],
    "status": "pending",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_name": "string",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start",
    "updated_at": "2019-08-24T14:15:22Z",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string",
    "workspace_owner_avatar_url": "string",
    "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
    "workspace_owner_name": "string"
  },
  "name": "string",
  "next_start_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "outdated": true,
  "owner_avatar_url": "string",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "shared_with": [
    {
      "actor_type": "group",
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "roles": [
        "admin"
      ]
    }
  ],
  "template_active_version_id": "b0da9c29-67d8-4c87-888c-bafe356f7f3c",
  "template_allow_user_cancel_workspace_jobs": true,
  "template_display_name": "string",
  "template_icon": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_name": "string",
  "template_require_active_version": true,
  "template_use_classic_parameter_flow": true,
  "ttl_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Properties

| Name                                        | Type                                                                    | Required | Restrictions | Description                                                                                                                                                                                                                                                                                                                                 |
|---------------------------------------------|-------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `allow_renames`                             | boolean                                                                 | false    |              | Allow renames is the effective rename permission for this workspace, derived from the template's allow_workspace_renames setting and the deprecated deployment-wide flag.                                                                                                                                                                   |
| `automatic_updates`                         | [codersdk.AutomaticUpdates](#codersdkautomaticupdates)                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `autostart_schedule`                        | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `created_at`                                | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `deleting_at`                               | string                                                                  | false    |              | Deleting at indicates the time at which the workspace will be permanently deleted. A workspace is eligible for deletion if it is dormant (a non-nil dormant_at value) and a value has been specified for time_til_dormant_autodelete on its template.                                                                                       |
| `dormant_at`                                | string                                                                  | false    |              | Dormant at being non-nil indicates a workspace that is dormant. A dormant workspace is no longer accessible must be activated. It is subject to deletion if it breaches the duration of the time_til_ field on its template.                                                                                                                |
| `favorite`                                  | boolean                                                                 | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `health`                                    | [codersdk.WorkspaceHealth](#codersdkworkspacehealth)                    | false    |              | Health shows the health of the workspace and information about what is causing an unhealthy status.                                                                                                                                                                                                                                         |
| `id`                                        | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `is_prebuild`                               | boolean                                                                 | false    |              | Is prebuild indicates whether the workspace is a prebuilt workspace. Prebuilt workspaces are owned by the prebuilds system user and have specific behavior, such as being managed differently from regular workspaces. Once a prebuilt workspace is claimed by a user, it transitions to a regular workspace, and IsPrebuild returns false. |
| `last_used_at`                              | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `latest_app_status`                         | [codersdk.WorkspaceAppStatus](#codersdkworkspaceappstatus)              | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `latest_build`                              | [codersdk.WorkspaceBuild](#codersdkworkspacebuild)                      | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `name`                                      | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `next_start_at`                             | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `organization_id`                           | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `organization_name`                         | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `outdated`                                  | boolean                                                                 | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `owner_avatar_url`                          | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `owner_id`                                  | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `owner_name`                                | string                                                                  | false    |              | Owner name is the username of the owner of the workspace.                                                                                                                                                                                                                                                                                   |
| `shared_with`                               | array of [codersdk.SharedWorkspaceActor](#codersdksharedworkspaceactor) | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `template_active_version_id`                | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `template_allow_user_cancel_workspace_jobs` | boolean                                                                 | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `template_display_name`                     | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `template_icon`                             | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `template_id`                               | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `template_name`                             | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `template_require_active_version`           | boolean                                                                 | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `template_use_classic_parameter_flow`       | boolean                                                                 | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `ttl_ms`                                    | integer                                                                 | false    |              |                                                                                                                                                                                                                                                                                                                                             |
| `updated_at`                                | string                                                                  | false    |              |                                                                                                                                                                                                                                                                                                                                             |

#### Enumerated Values

| Property            | Value(s)          |
|---------------------|-------------------|
| `automatic_updates` | `always`, `never` |

## codersdk.WorkspaceACL

```json
{
  "group": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "members": [
        {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        }
      ],
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "role": "admin",
      "source": "user",
      "total_member_count": 0
    }
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "role": "admin",
      "username": "string"
    }
  ]
}
```

### Properties

| Name    | Type                                                        | Required | Restrictions | Description |
|---------|-------------------------------------------------------------|----------|--------------|-------------|
| `group` | array of [codersdk.WorkspaceGroup](#codersdkworkspacegroup) | false    |              |             |
| `users` | array of [codersdk.WorkspaceUser](#codersdkworkspaceuser)   | false    |              |             |

## codersdk.WorkspaceAgent

```json
{
  "api_version": "string",
  "apps": [
    {
      "command": "string",
      "display_name": "string",
      "external": true,
      "group": "string",
      "health": "disabled",
      "healthcheck": {
        "interval": 0,
        "threshold": 0,
        "url": "string"
      },
      "hidden": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "open_in": "slim-window",
      "sharing_level": "owner",
      "slug": "string",
      "statuses": [
        {
          "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
          "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
          "created_at": "2019-08-24T14:15:22Z",
          "icon": "string",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "message": "string",
          "needs_user_attention": true,
          "state": "working",
          "uri": "string",
          "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
        }
      ],
      "subdomain": true,
      "subdomain_name": "string",
      "tooltip": "string",
      "url": "string"
    }
  ],
  "architecture": "string",
  "connection_timeout_seconds": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "directory": "string",
  "disconnected_at": "2019-08-24T14:15:22Z",
  "display_apps": [
    "vscode"
  ],
  "environment_variables": {
    "property1": "string",
    "property2": "string"
  },
  "expanded_directory": "string",
  "first_connected_at": "2019-08-24T14:15:22Z",
  "health": {
    "healthy": false,
    "reason": "agent has lost connection"
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "instance_id": "string",
  "last_connected_at": "2019-08-24T14:15:22Z",
  "latency": {
    "property1": {
      "latency_ms": 0,
      "preferred": true
    },
    "property2": {
      "latency_ms": 0,
      "preferred": true
    }
  },
  "lifecycle_state": "created",
  "log_sources": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "display_name": "string",
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
    }
  ],
  "logs_length": 0,
  "logs_overflowed": true,
  "metadata": [
    {
      "description": {
        "display_name": "string",
        "interval": 0,
        "key": "string",
        "script": "string",
        "timeout": 0
      },
      "result": {
        "age": 0,
        "collected_at": "2019-08-24T14:15:22Z",
        "error": "string",
        "value": "string"
      }
    }
  ],
  "name": "string",
  "operating_system": "string",
  "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
  "ready_at": "2019-08-24T14:15:22Z",
  "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
  "scripts": [
    {
      "cron": "string",
      "display_name": "string",
      "exit_code": 0,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "log_path": "string",
      "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
      "run_on_start": true,
      "run_on_stop": true,
      "script": "string",
      "start_blocks_login": true,
      "status": "ok",
      "timeout": 0
    }
  ],
  "started_at": "2019-08-24T14:15:22Z",
  "startup_script_behavior": "blocking",
  "status": "connecting",
  "subsystems": [
    "envbox"
  ],
  "troubleshooting_url": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "version": "string"
}
```

### Properties

| Name                         | Type                                                                                         | Required | Restrictions | Description                                                                                                                                                                                                                                                            |
|------------------------------|----------------------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api_version`                | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `apps`                       | array of [codersdk.WorkspaceApp](#codersdkworkspaceapp)                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `architecture`               | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `connection_timeout_seconds` | integer                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `created_at`                 | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `directory`                  | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `disconnected_at`            | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `display_apps`               | array of [codersdk.DisplayApp](#codersdkdisplayapp)                                          | false    |              |                                                                                                                                                                                                                                                                        |
| `environment_variables`      | object                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| » `[any property]`           | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `expanded_directory`         | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `first_connected_at`         | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `health`                     | [codersdk.WorkspaceAgentHealth](#codersdkworkspaceagenthealth)                               | false    |              | Health reports the health of the agent.                                                                                                                                                                                                                                |
| `id`                         | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `instance_id`                | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `last_connected_at`          | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `latency`                    | object                                                                                       | false    |              | Latency is mapped by region name (e.g. "New York City", "Seattle").                                                                                                                                                                                                    |
| » `[any property]`           | [codersdk.DERPRegion](#codersdkderpregion)                                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `lifecycle_state`            | [codersdk.WorkspaceAgentLifecycle](#codersdkworkspaceagentlifecycle)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `log_sources`                | array of [codersdk.WorkspaceAgentLogSource](#codersdkworkspaceagentlogsource)                | false    |              |                                                                                                                                                                                                                                                                        |
| `logs_length`                | integer                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `logs_overflowed`            | boolean                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `metadata`                   | array of [codersdk.WorkspaceAgentMetadata](#codersdkworkspaceagentmetadata)                  | false    |              | Metadata is only populated on the workspaces list endpoint when the request opts in with the include_agent_metadata search key, and it only carries the requested keys. The description's script is always empty here: it can be long, and list consumers want values. |
| `name`                       | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `operating_system`           | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `parent_id`                  | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `ready_at`                   | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `resource_id`                | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `scripts`                    | array of [codersdk.WorkspaceAgentScript](#codersdkworkspaceagentscript)                      | false    |              |                                                                                                                                                                                                                                                                        |
| `started_at`                 | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `startup_script_behavior`    | [codersdk.WorkspaceAgentStartupScriptBehavior](#codersdkworkspaceagentstartupscriptbehavior) | false    |              | Startup script behavior is a legacy field that is deprecated in favor of the `coder_script` resource. It's only referenced by old clients. Deprecated: Remove in the future!                                                                                           |
| `status`                     | [codersdk.WorkspaceAgentStatus](#codersdkworkspaceagentstatus)                               | false    |              |                                                                                                                                                                                                                                                                        |
| `subsystems`                 | array of [codersdk.AgentSubsystem](#codersdkagentsubsystem)                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `troubleshooting_url`        | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `updated_at`                 | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |
| `version`                    | string                                                                                       | false    |              |                                                                                                                                                                                                                                                                        |

## codersdk.WorkspaceAgentContainer

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": "string",
  "image": "string",
  "labels": {
    "property1": "string",
    "property2": "string"
  },
  "name": "string",
  "ports": [
    {
      "host_ip": "string",
      "host_port": 0,
      "network": "string",
      "port": 0
    }
  ],
  "running": true,
  "status": "string",
  "volumes": {
    "property1": "string",
    "property2": "string"
  }
}
```

### Properties

| Name               | Type                                                                                  | Required | Restrictions | Description                                                                                                                                |
|--------------------|---------------------------------------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------|
| `created_at`       | string                                                                                | false    |              | Created at is the time the container was created.                                                                                          |
| `id`               | string                                                                                | false    |              | ID is the unique identifier of the container.                                                                                              |
| `image`            | string                                                                                | false    |              | Image is the name of the container image.                                                                                                  |
| `labels`           | object                                                                                | false    |              | Labels is a map of key-value pairs of container labels.                                                                                    |
| » `[any property]` | string                                                                                | false    |              |                                                                                                                                            |
| `name`             | string                                                                                | false    |              | Name is the human-readable name of the container.                                                                                          |
| `ports`            | array of [codersdk.WorkspaceAgentContainerPort](#codersdkworkspaceagentcontainerport) | false    |              | Ports includes ports exposed by the container.                                                                                             |
| `running`          | boolean                                                                               | false    |              | Running is true if the container is currently running.                                                                                     |
| `status`           | string                                                                                | false    |              | Status is the current status of the container. This is somewhat implementation-dependent, but should generally be a human-readable string. |
| `volumes`          | object                                                                                | false    |              | Volumes is a map of "things" mounted into the container. Again, this is somewhat implementation-dependent.                                 |
| » `[any property]` | string                                                                                | false    |              |                                                                                                                                            |

## codersdk.WorkspaceAgentContainerPort

```json
{
  "host_ip": "string",
  "host_port": 0,
  "network": "string",
  "port": 0
}
```

### Properties

| Name        | Type    | Required | Restrictions | Description                                                                                                                |
|-------------|---------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------|
| `host_ip`   | string  | false    |              | Host ip is the IP address of the host interface to which the port is bound. Note that this can be an IPv4 or IPv6 address. |
| `host_port` | integer | false    |              | Host port is the port number *outside* the container.                                                                      |
| `network`   | string  | false    |              | Network is the network protocol used by the port (tcp, udp, etc).                                                          |
| `port`      | integer | false    |              | Port is the port number *inside* the container.                                                                            |

## codersdk.WorkspaceAgentDevcontainer

```json
{
  "agent": {
    "directory": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string"
  },
  "config_path": "string",
  "container": {
    "created_at": "2019-08-24T14:15:22Z",
    "id": "string",
    "image": "string",
    "labels": {
      "property1": "string",
      "property2": "string"
    },
    "name": "string",
    "ports": [
      {
        "host_ip": "string",
        "host_port": 0,
        "network": "string",
        "port": 0
      }
    ],
    "running": true,
    "status": "string",
    "volumes": {
      "property1": "string",
      "property2": "string"
    }
  },
  "dirty": true,
  "error": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "status": "running",
  "subagent_id": "7b85d465-b649-4b8b-9da8-5f731c1d294d",
  "workspace_folder": "string"
}
```

### Properties

| Name               | Type                                                                                   | Required | Restrictions | Description                |
|--------------------|----------------------------------------------------------------------------------------|----------|--------------|----------------------------|
| `agent`            | [codersdk.WorkspaceAgentDevcontainerAgent](#codersdkworkspaceagentdevcontaineragent)   | false    |              |                            |
| `config_path`      | string                                                                                 | false    |              |                            |
| `container`        | [codersdk.WorkspaceAgentContainer](#codersdkworkspaceagentcontainer)                   | false    |              |                            |
| `dirty`            | boolean                                                                                | false    |              |                            |
| `error`            | string                                                                                 | false    |              |                            |
| `id`               | string                                                                                 | false    |              |                            |
| `name`             | string                                                                                 | false    |              |                            |
| `status`           | [codersdk.WorkspaceAgentDevcontainerStatus](#codersdkworkspaceagentdevcontainerstatus) | false    |              | Additional runtime fields. |
| `subagent_id`      | string                                                                                 | false    |              |                            |
| `workspace_folder` | string                                                                                 | false    |              |                            |

## codersdk.WorkspaceAgentDevcontainerAgent

```json
{
  "directory": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string"
}
```

### Properties

| Name        | Type   | Required | Restrictions | Description |
|-------------|--------|----------|--------------|-------------|
| `directory` | string | false    |              |             |
| `id`        | string | false    |              |             |
| `name`      | string | false    |              |             |

## codersdk.WorkspaceAgentDevcontainerStatus

```json
"running"
```

### Properties

#### Enumerated Values

| Value(s)                                                          |
|-------------------------------------------------------------------|
| `deleting`, `error`, `running`, `starting`, `stopped`, `stopping` |

## codersdk.WorkspaceAgentGitServerMessage

```json
{
  "message": "string",
  "repositories": [
    {
      "branch": "string",
      "remote_origin": "string",
      "removed": true,
      "repo_root": "string",
      "unified_diff": "string"
    }
  ],
  "scanned_at": "2019-08-24T14:15:22Z",
  "type": "changes"
}
```

### Properties

| Name           | Type                                                                                       | Required | Restrictions | Description |
|----------------|--------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `message`      | string                                                                                     | false    |              |             |
| `repositories` | array of [codersdk.WorkspaceAgentRepoChanges](#codersdkworkspaceagentrepochanges)          | false    |              |             |
| `scanned_at`   | string                                                                                     | false    |              |             |
| `type`         | [codersdk.WorkspaceAgentGitServerMessageType](#codersdkworkspaceagentgitservermessagetype) | false    |              |             |

## codersdk.WorkspaceAgentGitServerMessageType

```json
"changes"
```

### Properties

#### Enumerated Values

| Value(s)           |
|--------------------|
| `changes`, `error` |

## codersdk.WorkspaceAgentHealth

```json
{
  "healthy": false,
  "reason": "agent has lost connection"
}
```

### Properties

| Name      | Type    | Required | Restrictions | Description                                                                                   |
|-----------|---------|----------|--------------|-----------------------------------------------------------------------------------------------|
| `healthy` | boolean | false    |              | Healthy is true if the agent is healthy.                                                      |
| `reason`  | string  | false    |              | Reason is a human-readable explanation of the agent's health. It is empty if Healthy is true. |

## codersdk.WorkspaceAgentLifecycle

```json
"created"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                     |
|------------------------------------------------------------------------------------------------------------------------------|
| `created`, `off`, `ready`, `shutdown_error`, `shutdown_timeout`, `shutting_down`, `start_error`, `start_timeout`, `starting` |

## codersdk.WorkspaceAgentListContainersResponse

```json
{
  "containers": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "id": "string",
      "image": "string",
      "labels": {
        "property1": "string",
        "property2": "string"
      },
      "name": "string",
      "ports": [
        {
          "host_ip": "string",
          "host_port": 0,
          "network": "string",
          "port": 0
        }
      ],
      "running": true,
      "status": "string",
      "volumes": {
        "property1": "string",
        "property2": "string"
      }
    }
  ],
  "devcontainers": [
    {
      "agent": {
        "directory": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string"
      },
      "config_path": "string",
      "container": {
        "created_at": "2019-08-24T14:15:22Z",
        "id": "string",
        "image": "string",
        "labels": {
          "property1": "string",
          "property2": "string"
        },
        "name": "string",
        "ports": [
          {
            "host_ip": "string",
            "host_port": 0,
            "network": "string",
            "port": 0
          }
        ],
        "running": true,
        "status": "string",
        "volumes": {
          "property1": "string",
          "property2": "string"
        }
      },
      "dirty": true,
      "error": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "status": "running",
      "subagent_id": "7b85d465-b649-4b8b-9da8-5f731c1d294d",
      "workspace_folder": "string"
    }
  ],
  "warnings": [
    "string"
  ]
}
```

### Properties

| Name            | Type                                                                                | Required | Restrictions | Description                                                                                                                           |
|-----------------|-------------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `containers`    | array of [codersdk.WorkspaceAgentContainer](#codersdkworkspaceagentcontainer)       | false    |              | Containers is a list of containers visible to the workspace agent.                                                                    |
| `devcontainers` | array of [codersdk.WorkspaceAgentDevcontainer](#codersdkworkspaceagentdevcontainer) | false    |              | Devcontainers is a list of devcontainers visible to the workspace agent.                                                              |
| `warnings`      | array of string                                                                     | false    |              | Warnings is a list of warnings that may have occurred during the process of listing containers. This should not include fatal errors. |

## codersdk.WorkspaceAgentListeningPort

```json
{
  "network": "string",
  "port": 0,
  "process_name": "string"
}
```

### Properties

| Name           | Type    | Required | Restrictions | Description              |
|----------------|---------|----------|--------------|--------------------------|
| `network`      | string  | false    |              | only "tcp" at the moment |
| `port`         | integer | false    |              |                          |
| `process_name` | string  | false    |              | may be empty             |

## codersdk.WorkspaceAgentListeningPortsResponse

```json
{
  "ports": [
    {
      "network": "string",
      "port": 0,
      "process_name": "string"
    }
  ]
}
```

### Properties

| Name    | Type                                                                                  | Required | Restrictions | Description                                                                                                                                                                                                                                            |
|---------|---------------------------------------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ports` | array of [codersdk.WorkspaceAgentListeningPort](#codersdkworkspaceagentlisteningport) | false    |              | If there are no ports in the list, nothing should be displayed in the UI. There must not be a "no ports available" message or anything similar, as there will always be no ports displayed on platforms where our port detection logic is unsupported. |

## codersdk.WorkspaceAgentLog

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "id": 0,
  "level": "trace",
  "output": "string",
  "source_id": "ae50a35c-df42-4eff-ba26-f8bc28d2af81"
}
```

### Properties

| Name         | Type                                   | Required | Restrictions | Description |
|--------------|----------------------------------------|----------|--------------|-------------|
| `created_at` | string                                 | false    |              |             |
| `id`         | integer                                | false    |              |             |
| `level`      | [codersdk.LogLevel](#codersdkloglevel) | false    |              |             |
| `output`     | string                                 | false    |              |             |
| `source_id`  | string                                 | false    |              |             |

## codersdk.WorkspaceAgentLogSource

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
}
```

### Properties

| Name                 | Type   | Required | Restrictions | Description |
|----------------------|--------|----------|--------------|-------------|
| `created_at`         | string | false    |              |             |
| `display_name`       | string | false    |              |             |
| `icon`               | string | false    |              |             |
| `id`                 | string | false    |              |             |
| `workspace_agent_id` | string | false    |              |             |

## codersdk.WorkspaceAgentMetadata

```json
{
  "description": {
    "display_name": "string",
    "interval": 0,
    "key": "string",
    "script": "string",
    "timeout": 0
  },
  "result": {
    "age": 0,
    "collected_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "value": "string"
  }
}
```

### Properties

| Name          | Type                                                                                     | Required | Restrictions | Description |
|---------------|------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `description` | [codersdk.WorkspaceAgentMetadataDescription](#codersdkworkspaceagentmetadatadescription) | false    |              |             |
| `result`      | [codersdk.WorkspaceAgentMetadataResult](#codersdkworkspaceagentmetadataresult)           | false    |              |             |

## codersdk.WorkspaceAgentMetadataDescription

```json
{
  "display_name": "string",
  "interval": 0,
  "key": "string",
  "script": "string",
  "timeout": 0
}
```

### Properties

| Name           | Type    | Required | Restrictions | Description |
|----------------|---------|----------|--------------|-------------|
| `display_name` | string  | false    |              |             |
| `interval`     | integer | false    |              |             |
| `key`          | string  | false    |              |             |
| `script`       | string  | false    |              |             |
| `timeout`      | integer | false    |              |             |

## codersdk.WorkspaceAgentMetadataResult

```json
{
  "age": 0,
  "collected_at": "2019-08-24T14:15:22Z",
  "error": "string",
  "value": "string"
}
```

### Properties

| Name           | Type    | Required | Restrictions | Description                                                                                                                             |
|----------------|---------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------|
| `age`          | integer | false    |              | Age is the number of seconds since the metadata was collected. It is provided in addition to CollectedAt to protect against clock skew. |
| `collected_at` | string  | false    |              |                                                                                                                                         |
| `error`        | string  | false    |              |                                                                                                                                         |
| `value`        | string  | false    |              |                                                                                                                                         |

## codersdk.WorkspaceAgentPortShare

```json
{
  "agent_name": "string",
  "port": 0,
  "protocol": "http",
  "share_level": "owner",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Properties

| Name           | Type                                                                                 | Required | Restrictions | Description |
|----------------|--------------------------------------------------------------------------------------|----------|--------------|-------------|
| `agent_name`   | string                                                                               | false    |              |             |
| `port`         | integer                                                                              | false    |              |             |
| `protocol`     | [codersdk.WorkspaceAgentPortShareProtocol](#codersdkworkspaceagentportshareprotocol) | false    |              |             |
| `share_level`  | [codersdk.WorkspaceAgentPortShareLevel](#codersdkworkspaceagentportsharelevel)       | false    |              |             |
| `workspace_id` | string                                                                               | false    |              |             |

#### Enumerated Values

| Property      | Value(s)                                           |
|---------------|----------------------------------------------------|
| `protocol`    | `http`, `https`                                    |
| `share_level` | `authenticated`, `organization`, `owner`, `public` |

## codersdk.WorkspaceAgentPortShareLevel

```json
"owner"
```

### Properties

#### Enumerated Values

| Value(s)                                           |
|----------------------------------------------------|
| `authenticated`, `organization`, `owner`, `public` |

## codersdk.WorkspaceAgentPortShareProtocol

```json
"http"
```

### Properties

#### Enumerated Values

| Value(s)        |
|-----------------|
| `http`, `https` |

## codersdk.WorkspaceAgentPortShares

```json
{
  "shares": [
    {
      "agent_name": "string",
      "port": 0,
      "protocol": "http",
      "share_level": "owner",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ]
}
```

### Properties

| Name     | Type                                                                          | Required | Restrictions | Description |
|----------|-------------------------------------------------------------------------------|----------|--------------|-------------|
| `shares` | array of [codersdk.WorkspaceAgentPortShare](#codersdkworkspaceagentportshare) | false    |              |             |

## codersdk.WorkspaceAgentRepoChanges

```json
{
  "branch": "string",
  "remote_origin": "string",
  "removed": true,
  "repo_root": "string",
  "unified_diff": "string"
}
```

### Properties

| Name            | Type    | Required | Restrictions | Description |
|-----------------|---------|----------|--------------|-------------|
| `branch`        | string  | false    |              |             |
| `remote_origin` | string  | false    |              |             |
| `removed`       | boolean | false    |              |             |
| `repo_root`     | string  | false    |              |             |
| `unified_diff`  | string  | false    |              |             |

## codersdk.WorkspaceAgentScript

```json
{
  "cron": "string",
  "display_name": "string",
  "exit_code": 0,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "log_path": "string",
  "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
  "run_on_start": true,
  "run_on_stop": true,
  "script": "string",
  "start_blocks_login": true,
  "status": "ok",
  "timeout": 0
}
```

### Properties

| Name                 | Type                                                                       | Required | Restrictions | Description |
|----------------------|----------------------------------------------------------------------------|----------|--------------|-------------|
| `cron`               | string                                                                     | false    |              |             |
| `display_name`       | string                                                                     | false    |              |             |
| `exit_code`          | integer                                                                    | false    |              |             |
| `id`                 | string                                                                     | false    |              |             |
| `log_path`           | string                                                                     | false    |              |             |
| `log_source_id`      | string                                                                     | false    |              |             |
| `run_on_start`       | boolean                                                                    | false    |              |             |
| `run_on_stop`        | boolean                                                                    | false    |              |             |
| `script`             | string                                                                     | false    |              |             |
| `start_blocks_login` | boolean                                                                    | false    |              |             |
| `status`             | [codersdk.WorkspaceAgentScriptStatus](#codersdkworkspaceagentscriptstatus) | false    |              |             |
| `timeout`            | integer                                                                    | false    |              |             |

## codersdk.WorkspaceAgentScriptStatus

```json
"ok"
```

### Properties

#### Enumerated Values

| Value(s)                                             |
|------------------------------------------------------|
| `exit_failure`, `ok`, `pipes_left_open`, `timed_out` |

## codersdk.WorkspaceAgentStartupScriptBehavior

```json
"blocking"
```

### Properties

#### Enumerated Values

| Value(s)                   |
|----------------------------|
| `blocking`, `non-blocking` |

## codersdk.WorkspaceAgentStatus

```json
"connecting"
```

### Properties

#### Enumerated Values

| Value(s)                                             |
|------------------------------------------------------|
| `connected`, `connecting`, `disconnected`, `timeout` |

## codersdk.WorkspaceApp

```json
{
  "command": "string",
  "display_name": "string",
  "external": true,
  "group": "string",
  "health": "disabled",
  "healthcheck": {
    "interval": 0,
    "threshold": 0,
    "url": "string"
  },
  "hidden": true,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "open_in": "slim-window",
  "sharing_level": "owner",
  "slug": "string",
  "statuses": [
    {
      "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
      "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
      "created_at": "2019-08-24T14:15:22Z",
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "message": "string",
      "needs_user_attention": true,
      "state": "working",
      "uri": "string",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
    }
  ],
  "subdomain": true,
  "subdomain_name": "string",
  "tooltip": "string",
  "url": "string"
}
```

### Properties

| Name             | Type                                                                   | Required | Restrictions | Description                                                                                                                                                                                                                                    |
|------------------|------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `command`        | string                                                                 | false    |              |                                                                                                                                                                                                                                                |
| `display_name`   | string                                                                 | false    |              | Display name is a friendly name for the app.                                                                                                                                                                                                   |
| `external`       | boolean                                                                | false    |              | External specifies whether the URL should be opened externally on the client or not.                                                                                                                                                           |
| `group`          | string                                                                 | false    |              |                                                                                                                                                                                                                                                |
| `health`         | [codersdk.WorkspaceAppHealth](#codersdkworkspaceapphealth)             | false    |              |                                                                                                                                                                                                                                                |
| `healthcheck`    | [codersdk.Healthcheck](#codersdkhealthcheck)                           | false    |              | Healthcheck specifies the configuration for checking app health.                                                                                                                                                                               |
| `hidden`         | boolean                                                                | false    |              |                                                                                                                                                                                                                                                |
| `icon`           | string                                                                 | false    |              | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard.                                                                                                                                               |
| `id`             | string                                                                 | false    |              |                                                                                                                                                                                                                                                |
| `open_in`        | [codersdk.WorkspaceAppOpenIn](#codersdkworkspaceappopenin)             | false    |              |                                                                                                                                                                                                                                                |
| `sharing_level`  | [codersdk.WorkspaceAppSharingLevel](#codersdkworkspaceappsharinglevel) | false    |              |                                                                                                                                                                                                                                                |
| `slug`           | string                                                                 | false    |              | Slug is a unique identifier within the agent.                                                                                                                                                                                                  |
| `statuses`       | array of [codersdk.WorkspaceAppStatus](#codersdkworkspaceappstatus)    | false    |              | Statuses is a list of statuses for the app.                                                                                                                                                                                                    |
| `subdomain`      | boolean                                                                | false    |              | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI. |
| `subdomain_name` | string                                                                 | false    |              | Subdomain name is the application domain exposed on the `coder server`.                                                                                                                                                                        |
| `tooltip`        | string                                                                 | false    |              | Tooltip is an optional markdown supported field that is displayed when hovering over workspace apps in the UI.                                                                                                                                 |
| `url`            | string                                                                 | false    |              | URL is the address being proxied to inside the workspace. If external is specified, this will be opened on the client.                                                                                                                         |

#### Enumerated Values

| Property        | Value(s)                                           |
|-----------------|----------------------------------------------------|
| `sharing_level` | `authenticated`, `organization`, `owner`, `public` |

## codersdk.WorkspaceAppHealth

```json
"disabled"
```

### Properties

#### Enumerated Values

| Value(s)                                           |
|----------------------------------------------------|
| `disabled`, `healthy`, `initializing`, `unhealthy` |

## codersdk.WorkspaceAppOpenIn

```json
"slim-window"
```

### Properties

#### Enumerated Values

| Value(s)             |
|----------------------|
| `slim-window`, `tab` |

## codersdk.WorkspaceAppSharingLevel

```json
"owner"
```

### Properties

#### Enumerated Values

| Value(s)                                           |
|----------------------------------------------------|
| `authenticated`, `organization`, `owner`, `public` |

## codersdk.WorkspaceAppStatus

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
  "created_at": "2019-08-24T14:15:22Z",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "message": "string",
  "needs_user_attention": true,
  "state": "working",
  "uri": "string",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
}
```

### Properties

| Name                   | Type                                                                 | Required | Restrictions | Description                                                                                                                                     |
|------------------------|----------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| `agent_id`             | string                                                               | false    |              |                                                                                                                                                 |
| `app_id`               | string                                                               | false    |              |                                                                                                                                                 |
| `created_at`           | string                                                               | false    |              |                                                                                                                                                 |
| `icon`                 | string                                                               | false    |              | Deprecated: This field is unused and will be removed in a future version. Icon is an external URL to an icon that will be rendered in the UI.   |
| `id`                   | string                                                               | false    |              |                                                                                                                                                 |
| `message`              | string                                                               | false    |              |                                                                                                                                                 |
| `needs_user_attention` | boolean                                                              | false    |              | Deprecated: This field is unused and will be removed in a future version. NeedsUserAttention specifies whether the status needs user attention. |
| `state`                | [codersdk.WorkspaceAppStatusState](#codersdkworkspaceappstatusstate) | false    |              |                                                                                                                                                 |
| `uri`                  | string                                                               | false    |              | Uri is the URI of the resource that the status is for. e.g. https://github.com/org/repo/pull/123 e.g. file:///path/to/file                      |
| `workspace_id`         | string                                                               | false    |              |                                                                                                                                                 |

## codersdk.WorkspaceAppStatusState

```json
"working"
```

### Properties

#### Enumerated Values

| Value(s)                                 |
|------------------------------------------|
| `complete`, `failure`, `idle`, `working` |

## codersdk.WorkspaceBuild

```json
{
  "build_number": 0,
  "created_at": "2019-08-24T14:15:22Z",
  "daily_cost": 0,
  "deadline": "2019-08-24T14:15:22Z",
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "initiator_name": "string",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "max_deadline": "2019-08-24T14:15:22Z",
  "reason": "initiator",
  "resources": [
    {
      "agents": [
        {
          "api_version": "string",
          "apps": [
            {
              "command": "string",
              "display_name": "string",
              "external": true,
              "group": "string",
              "health": "disabled",
              "healthcheck": {
                "interval": 0,
                "threshold": 0,
                "url": "string"
              },
              "hidden": true,
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "open_in": "slim-window",
              "sharing_level": "owner",
              "slug": "string",
              "statuses": [
                {
                  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                  "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                  "created_at": "2019-08-24T14:15:22Z",
                  "icon": "string",
                  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                  "message": "string",
                  "needs_user_attention": true,
                  "state": "working",
                  "uri": "string",
                  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                }
              ],
              "subdomain": true,
              "subdomain_name": "string",
              "tooltip": "string",
              "url": "string"
            }
          ],
          "architecture": "string",
          "connection_timeout_seconds": 0,
          "created_at": "2019-08-24T14:15:22Z",
          "directory": "string",
          "disconnected_at": "2019-08-24T14:15:22Z",
          "display_apps": [
            "vscode"
          ],
          "environment_variables": {
            "property1": "string",
            "property2": "string"
          },
          "expanded_directory": "string",
          "first_connected_at": "2019-08-24T14:15:22Z",
          "health": {
            "healthy": false,
            "reason": "agent has lost connection"
          },
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "instance_id": "string",
          "last_connected_at": "2019-08-24T14:15:22Z",
          "latency": {
            "property1": {
              "latency_ms": 0,
              "preferred": true
            },
            "property2": {
              "latency_ms": 0,
              "preferred": true
            }
          },
          "lifecycle_state": "created",
          "log_sources": [
            {
              "created_at": "2019-08-24T14:15:22Z",
              "display_name": "string",
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
            }
          ],
          "logs_length": 0,
          "logs_overflowed": true,
          "metadata": [
            {
              "description": {
                "display_name": "string",
                "interval": 0,
                "key": "string",
                "script": "string",
                "timeout": 0
              },
              "result": {
                "age": 0,
                "collected_at": "2019-08-24T14:15:22Z",
                "error": "string",
                "value": "string"
              }
            }
          ],
          "name": "string",
          "operating_system": "string",
          "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
          "ready_at": "2019-08-24T14:15:22Z",
          "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
          "scripts": [
            {
              "cron": "string",
              "display_name": "string",
              "exit_code": 0,
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "log_path": "string",
              "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
              "run_on_start": true,
              "run_on_stop": true,
              "script": "string",
              "start_blocks_login": true,
              "status": "ok",
              "timeout": 0
            }
          ],
          "started_at": "2019-08-24T14:15:22Z",
          "startup_script_behavior": "blocking",
          "status": "connecting",
          "subsystems": [
            "envbox"
          ],
          "troubleshooting_url": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "version": "string"
        }
      ],
      "created_at": "2019-08-24T14:15:22Z",
      "daily_cost": 0,
      "hide": true,
      "icon": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
      "metadata": [
        {
          "key": "string",
          "sensitive": true,
          "value": "string"
        }
      ],
      "name": "string",
      "type": "string",
      "workspace_transition": "start"
    }
  ],
  "status": "pending",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_name": "string",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "transition": "start",
  "updated_at": "2019-08-24T14:15:22Z",
  "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
  "workspace_name": "string",
  "workspace_owner_avatar_url": "string",
  "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
  "workspace_owner_name": "string"
}
```

### Properties

| Name                         | Type                                                              | Required | Restrictions | Description                                                         |
|------------------------------|-------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------|
| `build_number`               | integer                                                           | false    |              |                                                                     |
| `created_at`                 | string                                                            | false    |              |                                                                     |
| `daily_cost`                 | integer                                                           | false    |              |                                                                     |
| `deadline`                   | string                                                            | false    |              |                                                                     |
| `has_external_agent`         | boolean                                                           | false    |              |                                                                     |
| `id`                         | string                                                            | false    |              |                                                                     |
| `initiator_id`               | string                                                            | false    |              |                                                                     |
| `initiator_name`             | string                                                            | false    |              |                                                                     |
| `job`                        | [codersdk.ProvisionerJob](#codersdkprovisionerjob)                | false    |              |                                                                     |
| `matched_provisioners`       | [codersdk.MatchedProvisioners](#codersdkmatchedprovisioners)      | false    |              |                                                                     |
| `max_deadline`               | string                                                            | false    |              |                                                                     |
| `reason`                     | [codersdk.BuildReason](#codersdkbuildreason)                      | false    |              |                                                                     |
| `resources`                  | array of [codersdk.WorkspaceResource](#codersdkworkspaceresource) | false    |              |                                                                     |
| `status`                     | [codersdk.WorkspaceStatus](#codersdkworkspacestatus)              | false    |              |                                                                     |
| `template_version_id`        | string                                                            | false    |              |                                                                     |
| `template_version_name`      | string                                                            | false    |              |                                                                     |
| `template_version_preset_id` | string                                                            | false    |              |                                                                     |
| `transition`                 | [codersdk.WorkspaceTransition](#codersdkworkspacetransition)      | false    |              |                                                                     |
| `updated_at`                 | string                                                            | false    |              |                                                                     |
| `workspace_id`               | string                                                            | false    |              |                                                                     |
| `workspace_name`             | string                                                            | false    |              |                                                                     |
| `workspace_owner_avatar_url` | string                                                            | false    |              |                                                                     |
| `workspace_owner_id`         | string                                                            | false    |              |                                                                     |
| `workspace_owner_name`       | string                                                            | false    |              | Workspace owner name is the username of the owner of the workspace. |

#### Enumerated Values

| Property     | Value(s)                                                                                                          |
|--------------|-------------------------------------------------------------------------------------------------------------------|
| `reason`     | `autostart`, `autostop`, `initiator`                                                                              |
| `status`     | `canceled`, `canceling`, `deleted`, `deleting`, `failed`, `pending`, `running`, `starting`, `stopped`, `stopping` |
| `transition` | `delete`, `start`, `stop`                                                                                         |

## codersdk.WorkspaceBuildDebugEventRequest

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}
```

### Properties

| Name | Type   | Required | Restrictions | Description                                                                     |
|------|--------|----------|--------------|---------------------------------------------------------------------------------|
| `id` | string | true     |              | ID identifies this click so a later step of the funnel can be attributed to it. |

## codersdk.WorkspaceBuildParameter

```json
{
  "name": "string",
  "value": "string"
}
```

### Properties

| Name    | Type   | Required | Restrictions | Description |
|---------|--------|----------|--------------|-------------|
| `name`  | string | false    |              |             |
| `value` | string | false    |              |             |

## codersdk.WorkspaceBuildTimings

```json
{
  "agent_connection_timings": [
    {
      "ended_at": "2019-08-24T14:15:22Z",
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z",
      "workspace_agent_id": "string",
      "workspace_agent_name": "string"
    }
  ],
  "agent_script_timings": [
    {
      "display_name": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "exit_code": 0,
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z",
      "status": "string",
      "workspace_agent_id": "string",
      "workspace_agent_name": "string"
    }
  ],
  "provisioner_timings": [
    {
      "action": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
      "resource": "string",
      "source": "string",
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z"
    }
  ]
}
```

### Properties

| Name                       | Type                                                                      | Required | Restrictions | Description                                                                                                      |
|----------------------------|---------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------|
| `agent_connection_timings` | array of [codersdk.AgentConnectionTiming](#codersdkagentconnectiontiming) | false    |              |                                                                                                                  |
| `agent_script_timings`     | array of [codersdk.AgentScriptTiming](#codersdkagentscripttiming)         | false    |              | Agent script timings Consolidate agent-related timing metrics into a single struct when updating the API version |
| `provisioner_timings`      | array of [codersdk.ProvisionerTiming](#codersdkprovisionertiming)         | false    |              |                                                                                                                  |

## codersdk.WorkspaceConnectionLatencyMS

```json
{
  "p50": 0,
  "p95": 0
}
```

### Properties

| Name  | Type   | Required | Restrictions | Description |
|-------|--------|----------|--------------|-------------|
| `p50` | number | false    |              |             |
| `p95` | number | false    |              |             |

## codersdk.WorkspaceDeploymentStats

```json
{
  "building": 0,
  "connection_latency_ms": {
    "p50": 0,
    "p95": 0
  },
  "failed": 0,
  "pending": 0,
  "running": 0,
  "rx_bytes": 0,
  "stopped": 0,
  "tx_bytes": 0
}
```

### Properties

| Name                    | Type                                                                           | Required | Restrictions | Description |
|-------------------------|--------------------------------------------------------------------------------|----------|--------------|-------------|
| `building`              | integer                                                                        | false    |              |             |
| `connection_latency_ms` | [codersdk.WorkspaceConnectionLatencyMS](#codersdkworkspaceconnectionlatencyms) | false    |              |             |
| `failed`                | integer                                                                        | false    |              |             |
| `pending`               | integer                                                                        | false    |              |             |
| `running`               | integer                                                                        | false    |              |             |
| `rx_bytes`              | integer                                                                        | false    |              |             |
| `stopped`               | integer                                                                        | false    |              |             |
| `tx_bytes`              | integer                                                                        | false    |              |             |

## codersdk.WorkspaceGroup

```json
{
  "avatar_url": "http://example.com",
  "display_name": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "members": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ],
  "name": "string",
  "organization_display_name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "quota_allowance": 0,
  "role": "admin",
  "source": "user",
  "total_member_count": 0
}
```

### Properties

| Name                        | Type                                                  | Required | Restrictions | Description                                                                                                                                                           |
|-----------------------------|-------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `avatar_url`                | string                                                | false    |              |                                                                                                                                                                       |
| `display_name`              | string                                                | false    |              |                                                                                                                                                                       |
| `id`                        | string                                                | false    |              |                                                                                                                                                                       |
| `members`                   | array of [codersdk.ReducedUser](#codersdkreduceduser) | false    |              |                                                                                                                                                                       |
| `name`                      | string                                                | false    |              |                                                                                                                                                                       |
| `organization_display_name` | string                                                | false    |              |                                                                                                                                                                       |
| `organization_id`           | string                                                | false    |              |                                                                                                                                                                       |
| `organization_name`         | string                                                | false    |              |                                                                                                                                                                       |
| `quota_allowance`           | integer                                               | false    |              |                                                                                                                                                                       |
| `role`                      | [codersdk.WorkspaceRole](#codersdkworkspacerole)      | false    |              |                                                                                                                                                                       |
| `source`                    | [codersdk.GroupSource](#codersdkgroupsource)          | false    |              |                                                                                                                                                                       |
| `total_member_count`        | integer                                               | false    |              | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. |

#### Enumerated Values

| Property | Value(s)       |
|----------|----------------|
| `role`   | `admin`, `use` |

## codersdk.WorkspaceHealth

```json
{
  "failing_agents": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "healthy": false
}
```

### Properties

| Name             | Type            | Required | Restrictions | Description                                                          |
|------------------|-----------------|----------|--------------|----------------------------------------------------------------------|
| `failing_agents` | array of string | false    |              | Failing agents lists the IDs of the agents that are failing, if any. |
| `healthy`        | boolean         | false    |              | Healthy is true if the workspace is healthy.                         |

## codersdk.WorkspaceProxy

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "deleted": true,
  "derp_enabled": true,
  "derp_only": true,
  "display_name": "string",
  "healthy": true,
  "icon_url": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "path_app_url": "string",
  "status": {
    "checked_at": "2019-08-24T14:15:22Z",
    "report": {
      "errors": [
        "string"
      ],
      "warnings": [
        "string"
      ]
    },
    "status": "ok"
  },
  "updated_at": "2019-08-24T14:15:22Z",
  "version": "string",
  "wildcard_hostname": "string"
}
```

### Properties

| Name                | Type                                                           | Required | Restrictions | Description                                                                                                                                                                       |
|---------------------|----------------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `created_at`        | string                                                         | false    |              |                                                                                                                                                                                   |
| `deleted`           | boolean                                                        | false    |              |                                                                                                                                                                                   |
| `derp_enabled`      | boolean                                                        | false    |              |                                                                                                                                                                                   |
| `derp_only`         | boolean                                                        | false    |              |                                                                                                                                                                                   |
| `display_name`      | string                                                         | false    |              |                                                                                                                                                                                   |
| `healthy`           | boolean                                                        | false    |              |                                                                                                                                                                                   |
| `icon_url`          | string                                                         | false    |              |                                                                                                                                                                                   |
| `id`                | string                                                         | false    |              |                                                                                                                                                                                   |
| `name`              | string                                                         | false    |              |                                                                                                                                                                                   |
| `path_app_url`      | string                                                         | false    |              | Path app URL is the URL to the base path for path apps. Optional unless wildcard_hostname is set. E.g. https://us.example.com                                                     |
| `status`            | [codersdk.WorkspaceProxyStatus](#codersdkworkspaceproxystatus) | false    |              | Status is the latest status check of the proxy. This will be empty for deleted proxies. This value can be used to determine if a workspace proxy is healthy and ready to use.     |
| `updated_at`        | string                                                         | false    |              |                                                                                                                                                                                   |
| `version`           | string                                                         | false    |              |                                                                                                                                                                                   |
| `wildcard_hostname` | string                                                         | false    |              | Wildcard hostname is the wildcard hostname for subdomain apps. E.g. *.us.example.com E.g.*--suffix.au.example.com Optional. Does not need to be on the same domain as PathAppURL. |

## codersdk.WorkspaceProxyStatus

```json
{
  "checked_at": "2019-08-24T14:15:22Z",
  "report": {
    "errors": [
      "string"
    ],
    "warnings": [
      "string"
    ]
  },
  "status": "ok"
}
```

### Properties

| Name         | Type                                                     | Required | Restrictions | Description                                                               |
|--------------|----------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------|
| `checked_at` | string                                                   | false    |              |                                                                           |
| `report`     | [codersdk.ProxyHealthReport](#codersdkproxyhealthreport) | false    |              | Report provides more information about the health of the workspace proxy. |
| `status`     | [codersdk.ProxyHealthStatus](#codersdkproxyhealthstatus) | false    |              |                                                                           |

## codersdk.WorkspaceQuota

```json
{
  "budget": 0,
  "credits_consumed": 0
}
```

### Properties

| Name               | Type    | Required | Restrictions | Description |
|--------------------|---------|----------|--------------|-------------|
| `budget`           | integer | false    |              |             |
| `credits_consumed` | integer | false    |              |             |

## codersdk.WorkspaceResource

```json
{
  "agents": [
    {
      "api_version": "string",
      "apps": [
        {
          "command": "string",
          "display_name": "string",
          "external": true,
          "group": "string",
          "health": "disabled",
          "healthcheck": {
            "interval": 0,
            "threshold": 0,
            "url": "string"
          },
          "hidden": true,
          "icon": "string",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "open_in": "slim-window",
          "sharing_level": "owner",
          "slug": "string",
          "statuses": [
            {
              "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
              "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
              "created_at": "2019-08-24T14:15:22Z",
              "icon": "string",
              "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
              "message": "string",
              "needs_user_attention": true,
              "state": "working",
              "uri": "string",
              "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
            }
          ],
          "subdomain": true,
          "subdomain_name": "string",
          "tooltip": "string",
          "url": "string"
        }
      ],
      "architecture": "string",
      "connection_timeout_seconds": 0,
      "created_at": "2019-08-24T14:15:22Z",
      "directory": "string",
      "disconnected_at": "2019-08-24T14:15:22Z",
      "display_apps": [
        "vscode"
      ],
      "environment_variables": {
        "property1": "string",
        "property2": "string"
      },
      "expanded_directory": "string",
      "first_connected_at": "2019-08-24T14:15:22Z",
      "health": {
        "healthy": false,
        "reason": "agent has lost connection"
      },
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "instance_id": "string",
      "last_connected_at": "2019-08-24T14:15:22Z",
      "latency": {
        "property1": {
          "latency_ms": 0,
          "preferred": true
        },
        "property2": {
          "latency_ms": 0,
          "preferred": true
        }
      },
      "lifecycle_state": "created",
      "log_sources": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "display_name": "string",
          "icon": "string",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
        }
      ],
      "logs_length": 0,
      "logs_overflowed": true,
      "metadata": [
        {
          "description": {
            "display_name": "string",
            "interval": 0,
            "key": "string",
            "script": "string",
            "timeout": 0
          },
          "result": {
            "age": 0,
            "collected_at": "2019-08-24T14:15:22Z",
            "error": "string",
            "value": "string"
          }
        }
      ],
      "name": "string",
      "operating_system": "string",
      "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
      "ready_at": "2019-08-24T14:15:22Z",
      "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
      "scripts": [
        {
          "cron": "string",
          "display_name": "string",
          "exit_code": 0,
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "log_path": "string",
          "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
          "run_on_start": true,
          "run_on_stop": true,
          "script": "string",
          "start_blocks_login": true,
          "status": "ok",
          "timeout": 0
        }
      ],
      "started_at": "2019-08-24T14:15:22Z",
      "startup_script_behavior": "blocking",
      "status": "connecting",
      "subsystems": [
        "envbox"
      ],
      "troubleshooting_url": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "version": "string"
    }
  ],
  "created_at": "2019-08-24T14:15:22Z",
  "daily_cost": 0,
  "hide": true,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
  "metadata": [
    {
      "key": "string",
      "sensitive": true,
      "value": "string"
    }
  ],
  "name": "string",
  "type": "string",
  "workspace_transition": "start"
}
```

### Properties

| Name                   | Type                                                                              | Required | Restrictions | Description |
|------------------------|-----------------------------------------------------------------------------------|----------|--------------|-------------|
| `agents`               | array of [codersdk.WorkspaceAgent](#codersdkworkspaceagent)                       | false    |              |             |
| `created_at`           | string                                                                            | false    |              |             |
| `daily_cost`           | integer                                                                           | false    |              |             |
| `hide`                 | boolean                                                                           | false    |              |             |
| `icon`                 | string                                                                            | false    |              |             |
| `id`                   | string                                                                            | false    |              |             |
| `job_id`               | string                                                                            | false    |              |             |
| `metadata`             | array of [codersdk.WorkspaceResourceMetadata](#codersdkworkspaceresourcemetadata) | false    |              |             |
| `name`                 | string                                                                            | false    |              |             |
| `type`                 | string                                                                            | false    |              |             |
| `workspace_transition` | [codersdk.WorkspaceTransition](#codersdkworkspacetransition)                      | false    |              |             |

#### Enumerated Values

| Property               | Value(s)                  |
|------------------------|---------------------------|
| `workspace_transition` | `delete`, `start`, `stop` |

## codersdk.WorkspaceResourceMetadata

```json
{
  "key": "string",
  "sensitive": true,
  "value": "string"
}
```

### Properties

| Name        | Type    | Required | Restrictions | Description |
|-------------|---------|----------|--------------|-------------|
| `key`       | string  | false    |              |             |
| `sensitive` | boolean | false    |              |             |
| `value`     | string  | false    |              |             |

## codersdk.WorkspaceRole

```json
"admin"
```

### Properties

#### Enumerated Values

| Value(s)           |
|--------------------|
| ``, `admin`, `use` |

## codersdk.WorkspaceSharingSettings

```json
{
  "shareable_workspace_owners": "none",
  "sharing_disabled": true,
  "sharing_globally_disabled": true
}
```

### Properties

| Name                         | Type                                                                   | Required | Restrictions | Description                                                                                                                     |
|------------------------------|------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------|
| `shareable_workspace_owners` | [codersdk.ShareableWorkspaceOwners](#codersdkshareableworkspaceowners) | false    |              | Shareable workspace owners controls whose workspaces can be shared within the organization.                                     |
| `sharing_disabled`           | boolean                                                                | false    |              | Sharing disabled is deprecated and left for backward compatibility purposes. Deprecated: use `ShareableWorkspaceOwners` instead |
| `sharing_globally_disabled`  | boolean                                                                | false    |              | Sharing globally disabled is true if sharing has been disabled for this organization because of a deployment-wide setting.      |

#### Enumerated Values

| Property                     | Value(s)                               |
|------------------------------|----------------------------------------|
| `shareable_workspace_owners` | `everyone`, `none`, `service_accounts` |

## codersdk.WorkspaceStatus

```json
"pending"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                          |
|-------------------------------------------------------------------------------------------------------------------|
| `canceled`, `canceling`, `deleted`, `deleting`, `failed`, `pending`, `running`, `starting`, `stopped`, `stopping` |

## codersdk.WorkspaceTransition

```json
"start"
```

### Properties

#### Enumerated Values

| Value(s)                  |
|---------------------------|
| `delete`, `start`, `stop` |

## codersdk.WorkspaceUser

```json
{
  "avatar_url": "http://example.com",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "role": "admin",
  "username": "string"
}
```

### Properties

| Name         | Type                                             | Required | Restrictions | Description |
|--------------|--------------------------------------------------|----------|--------------|-------------|
| `avatar_url` | string                                           | false    |              |             |
| `id`         | string                                           | true     |              |             |
| `name`       | string                                           | false    |              |             |
| `role`       | [codersdk.WorkspaceRole](#codersdkworkspacerole) | false    |              |             |
| `username`   | string                                           | true     |              |             |

#### Enumerated Values

| Property | Value(s)       |
|----------|----------------|
| `role`   | `admin`, `use` |

## codersdk.WorkspacesResponse

```json
{
  "count": 0,
  "workspaces": [
    {
      "allow_renames": true,
      "automatic_updates": "always",
      "autostart_schedule": "string",
      "created_at": "2019-08-24T14:15:22Z",
      "deleting_at": "2019-08-24T14:15:22Z",
      "dormant_at": "2019-08-24T14:15:22Z",
      "favorite": true,
      "health": {
        "failing_agents": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "healthy": false
      },
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_prebuild": true,
      "last_used_at": "2019-08-24T14:15:22Z",
      "latest_app_status": {
        "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
        "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
        "created_at": "2019-08-24T14:15:22Z",
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "message": "string",
        "needs_user_attention": true,
        "state": "working",
        "uri": "string",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
      },
      "latest_build": {
        "build_number": 0,
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "deadline": "2019-08-24T14:15:22Z",
        "has_external_agent": true,
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
        "initiator_name": "string",
        "job": {
          "available_workers": [
            "497f6eca-6276-4993-bfeb-53cbbbba6f08"
          ],
          "canceled_at": "2019-08-24T14:15:22Z",
          "completed_at": "2019-08-24T14:15:22Z",
          "created_at": "2019-08-24T14:15:22Z",
          "error": "string",
          "error_code": "REQUIRED_TEMPLATE_VARIABLES",
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
          "input": {
            "error": "string",
            "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
            "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
          },
          "logs_overflowed": true,
          "metadata": {
            "template_display_name": "string",
            "template_icon": "string",
            "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
            "template_name": "string",
            "template_version_name": "string",
            "workspace_build_transition": "start",
            "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
            "workspace_name": "string"
          },
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "queue_position": 0,
          "queue_size": 0,
          "started_at": "2019-08-24T14:15:22Z",
          "status": "pending",
          "tags": {
            "property1": "string",
            "property2": "string"
          },
          "type": "template_version_import",
          "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
          "worker_name": "string"
        },
        "matched_provisioners": {
          "available": 0,
          "count": 0,
          "most_recently_seen": "2019-08-24T14:15:22Z"
        },
        "max_deadline": "2019-08-24T14:15:22Z",
        "reason": "initiator",
        "resources": [
          {
            "agents": [
              {
                "api_version": "string",
                "apps": [
                  {
                    "command": "string",
                    "display_name": "string",
                    "external": true,
                    "group": "string",
                    "health": "disabled",
                    "healthcheck": {},
                    "hidden": true,
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "open_in": "slim-window",
                    "sharing_level": "owner",
                    "slug": "string",
                    "statuses": [],
                    "subdomain": true,
                    "subdomain_name": "string",
                    "tooltip": "string",
                    "url": "string"
                  }
                ],
                "architecture": "string",
                "connection_timeout_seconds": 0,
                "created_at": "2019-08-24T14:15:22Z",
                "directory": "string",
                "disconnected_at": "2019-08-24T14:15:22Z",
                "display_apps": [
                  "vscode"
                ],
                "environment_variables": {
                  "property1": "string",
                  "property2": "string"
                },
                "expanded_directory": "string",
                "first_connected_at": "2019-08-24T14:15:22Z",
                "health": {
                  "healthy": false,
                  "reason": "agent has lost connection"
                },
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "instance_id": "string",
                "last_connected_at": "2019-08-24T14:15:22Z",
                "latency": {
                  "property1": {
                    "latency_ms": 0,
                    "preferred": true
                  },
                  "property2": {
                    "latency_ms": 0,
                    "preferred": true
                  }
                },
                "lifecycle_state": "created",
                "log_sources": [
                  {
                    "created_at": "2019-08-24T14:15:22Z",
                    "display_name": "string",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
                  }
                ],
                "logs_length": 0,
                "logs_overflowed": true,
                "metadata": [
                  {
                    "description": {},
                    "result": {}
                  }
                ],
                "name": "string",
                "operating_system": "string",
                "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
                "ready_at": "2019-08-24T14:15:22Z",
                "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
                "scripts": [
                  {
                    "cron": "string",
                    "display_name": "string",
                    "exit_code": 0,
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "log_path": "string",
                    "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                    "run_on_start": true,
                    "run_on_stop": true,
                    "script": "string",
                    "start_blocks_login": true,
                    "status": "ok",
                    "timeout": 0
                  }
                ],
                "started_at": "2019-08-24T14:15:22Z",
                "startup_script_behavior": "blocking",
                "status": "connecting",
                "subsystems": [
                  "envbox"
                ],
                "troubleshooting_url": "string",
                "updated_at": "2019-08-24T14:15:22Z",
                "version": "string"
              }
            ],
            "created_at": "2019-08-24T14:15:22Z",
            "daily_cost": 0,
            "hide": true,
            "icon": "string",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
            "metadata": [
              {
                "key": "string",
                "sensitive": true,
                "value": "string"
              }
            ],
            "name": "string",
            "type": "string",
            "workspace_transition": "start"
          }
        ],
        "status": "pending",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "template_version_name": "string",
        "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
        "transition": "start",
        "updated_at": "2019-08-24T14:15:22Z",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string",
        "workspace_owner_avatar_url": "string",
        "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
        "workspace_owner_name": "string"
      },
      "name": "string",
      "next_start_at": "2019-08-24T14:15:22Z",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "outdated": true,
      "owner_avatar_url": "string",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "owner_name": "string",
      "shared_with": [
        {
          "actor_type": "group",
          "avatar_url": "http://example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "name": "string",
          "roles": [
            "admin"
          ]
        }
      ],
      "template_active_version_id": "b0da9c29-67d8-4c87-888c-bafe356f7f3c",
      "template_allow_user_cancel_workspace_jobs": true,
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_require_active_version": true,
      "template_use_classic_parameter_flow": true,
      "ttl_ms": 0,
      "updated_at": "2019-08-24T14:15:22Z"
    }
  ]
}
```

### Properties

| Name         | Type                                              | Required | Restrictions | Description |
|--------------|---------------------------------------------------|----------|--------------|-------------|
| `count`      | integer                                           | false    |              |             |
| `workspaces` | array of [codersdk.Workspace](#codersdkworkspace) | false    |              |             |

## derp.BytesSentRecv

```json
{
  "key": {},
  "recv": 0,
  "sent": 0
}
```

### Properties

| Name   | Type                             | Required | Restrictions | Description                                                          |
|--------|----------------------------------|----------|--------------|----------------------------------------------------------------------|
| `key`  | [key.NodePublic](#keynodepublic) | false    |              | Key is the public key of the client which sent/received these bytes. |
| `recv` | integer                          | false    |              |                                                                      |
| `sent` | integer                          | false    |              |                                                                      |

## derp.ServerInfoMessage

```json
{
  "tokenBucketBytesBurst": 0,
  "tokenBucketBytesPerSecond": 0
}
```

### Properties

|Name|Type|Required|Restrictions|Description|
|---|---|---|---|---|
|`tokenBucketBytesBurst`|integer|false||Tokenbucketbytesburst is how many bytes the server will allow to burst, temporarily violating TokenBucketBytesPerSecond.
Zero means unspecified. There might be a limit, but the client need not try to respect it.|
|`tokenBucketBytesPerSecond`|integer|false||Tokenbucketbytespersecond is how many bytes per second the server says it will accept, including all framing bytes.
Zero means unspecified. There might be a limit, but the client need not try to respect it.|

## health.Code

```json
"EUNKNOWN"
```

### Properties

#### Enumerated Values

| Value(s)                                                                                                                                                                               |
|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `EACS01`, `EACS02`, `EACS03`, `EACS04`, `EDB01`, `EDB02`, `EDERP01`, `EDERP02`, `EDERP03`, `EPD01`, `EPD02`, `EPD03`, `EUNKNOWN`, `EWP01`, `EWP02`, `EWP04`, `EWS01`, `EWS02`, `EWS03` |

## health.Message

```json
{
  "code": "EUNKNOWN",
  "message": "string"
}
```

### Properties

| Name      | Type                       | Required | Restrictions | Description |
|-----------|----------------------------|----------|--------------|-------------|
| `code`    | [health.Code](#healthcode) | false    |              |             |
| `message` | string                     | false    |              |             |

## health.Severity

```json
"ok"
```

### Properties

#### Enumerated Values

| Value(s)                 |
|--------------------------|
| `error`, `ok`, `warning` |

## healthsdk.AccessURLReport

```json
{
  "access_url": "string",
  "dismissed": true,
  "error": "string",
  "healthy": true,
  "healthz_response": "string",
  "reachable": true,
  "severity": "ok",
  "status_code": 0,
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ]
}
```

### Properties

| Name               | Type                                      | Required | Restrictions | Description                                                                                 |
|--------------------|-------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------|
| `access_url`       | string                                    | false    |              |                                                                                             |
| `dismissed`        | boolean                                   | false    |              |                                                                                             |
| `error`            | string                                    | false    |              |                                                                                             |
| `healthy`          | boolean                                   | false    |              | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
| `healthz_response` | string                                    | false    |              |                                                                                             |
| `reachable`        | boolean                                   | false    |              |                                                                                             |
| `severity`         | [health.Severity](#healthseverity)        | false    |              |                                                                                             |
| `status_code`      | integer                                   | false    |              |                                                                                             |
| `warnings`         | array of [health.Message](#healthmessage) | false    |              |                                                                                             |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## healthsdk.DERPHealthReport

```json
{
  "dismissed": true,
  "error": "string",
  "healthy": true,
  "netcheck": {
    "captivePortal": "string",
    "globalV4": "string",
    "globalV6": "string",
    "icmpv4": true,
    "ipv4": true,
    "ipv4CanSend": true,
    "ipv6": true,
    "ipv6CanSend": true,
    "mappingVariesByDestIP": "string",
    "oshasIPv6": true,
    "pcp": "string",
    "pmp": "string",
    "preferredDERP": 0,
    "regionLatency": {
      "property1": 0,
      "property2": 0
    },
    "regionV4Latency": {
      "property1": 0,
      "property2": 0
    },
    "regionV6Latency": {
      "property1": 0,
      "property2": 0
    },
    "udp": true,
    "upnP": "string"
  },
  "netcheck_err": "string",
  "netcheck_logs": [
    "string"
  ],
  "regions": {
    "property1": {
      "error": "string",
      "healthy": true,
      "node_reports": [
        {
          "can_exchange_messages": true,
          "client_errs": [
            [
              "string"
            ]
          ],
          "client_logs": [
            [
              "string"
            ]
          ],
          "error": "string",
          "healthy": true,
          "node": {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          },
          "node_info": {
            "tokenBucketBytesBurst": 0,
            "tokenBucketBytesPerSecond": 0
          },
          "round_trip_ping": "string",
          "round_trip_ping_ms": 0,
          "severity": "ok",
          "stun": {
            "canSTUN": true,
            "enabled": true,
            "error": "string"
          },
          "uses_websocket": true,
          "warnings": [
            {
              "code": "EUNKNOWN",
              "message": "string"
            }
          ]
        }
      ],
      "region": {
        "avoid": true,
        "embeddedRelay": true,
        "nodes": [
          {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          }
        ],
        "regionCode": "string",
        "regionID": 0,
        "regionName": "string"
      },
      "severity": "ok",
      "warnings": [
        {
          "code": "EUNKNOWN",
          "message": "string"
        }
      ]
    },
    "property2": {
      "error": "string",
      "healthy": true,
      "node_reports": [
        {
          "can_exchange_messages": true,
          "client_errs": [
            [
              "string"
            ]
          ],
          "client_logs": [
            [
              "string"
            ]
          ],
          "error": "string",
          "healthy": true,
          "node": {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          },
          "node_info": {
            "tokenBucketBytesBurst": 0,
            "tokenBucketBytesPerSecond": 0
          },
          "round_trip_ping": "string",
          "round_trip_ping_ms": 0,
          "severity": "ok",
          "stun": {
            "canSTUN": true,
            "enabled": true,
            "error": "string"
          },
          "uses_websocket": true,
          "warnings": [
            {
              "code": "EUNKNOWN",
              "message": "string"
            }
          ]
        }
      ],
      "region": {
        "avoid": true,
        "embeddedRelay": true,
        "nodes": [
          {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          }
        ],
        "regionCode": "string",
        "regionID": 0,
        "regionName": "string"
      },
      "severity": "ok",
      "warnings": [
        {
          "code": "EUNKNOWN",
          "message": "string"
        }
      ]
    }
  },
  "severity": "ok",
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ]
}
```

### Properties

| Name               | Type                                                     | Required | Restrictions | Description                                                                                 |
|--------------------|----------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------|
| `dismissed`        | boolean                                                  | false    |              |                                                                                             |
| `error`            | string                                                   | false    |              |                                                                                             |
| `healthy`          | boolean                                                  | false    |              | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
| `netcheck`         | [netcheck.Report](#netcheckreport)                       | false    |              |                                                                                             |
| `netcheck_err`     | string                                                   | false    |              |                                                                                             |
| `netcheck_logs`    | array of string                                          | false    |              |                                                                                             |
| `regions`          | object                                                   | false    |              |                                                                                             |
| » `[any property]` | [healthsdk.DERPRegionReport](#healthsdkderpregionreport) | false    |              |                                                                                             |
| `severity`         | [health.Severity](#healthseverity)                       | false    |              |                                                                                             |
| `warnings`         | array of [health.Message](#healthmessage)                | false    |              |                                                                                             |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## healthsdk.DERPNodeReport

```json
{
  "can_exchange_messages": true,
  "client_errs": [
    [
      "string"
    ]
  ],
  "client_logs": [
    [
      "string"
    ]
  ],
  "error": "string",
  "healthy": true,
  "node": {
    "canPort80": true,
    "certName": "string",
    "derpport": 0,
    "forceHTTP": true,
    "hostName": "string",
    "insecureForTests": true,
    "ipv4": "string",
    "ipv6": "string",
    "name": "string",
    "regionID": 0,
    "stunonly": true,
    "stunport": 0,
    "stuntestIP": "string"
  },
  "node_info": {
    "tokenBucketBytesBurst": 0,
    "tokenBucketBytesPerSecond": 0
  },
  "round_trip_ping": "string",
  "round_trip_ping_ms": 0,
  "severity": "ok",
  "stun": {
    "canSTUN": true,
    "enabled": true,
    "error": "string"
  },
  "uses_websocket": true,
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ]
}
```

### Properties

| Name                    | Type                                             | Required | Restrictions | Description                                                                                 |
|-------------------------|--------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------|
| `can_exchange_messages` | boolean                                          | false    |              |                                                                                             |
| `client_errs`           | array of array                                   | false    |              |                                                                                             |
| `client_logs`           | array of array                                   | false    |              |                                                                                             |
| `error`                 | string                                           | false    |              |                                                                                             |
| `healthy`               | boolean                                          | false    |              | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
| `node`                  | [tailcfg.DERPNode](#tailcfgderpnode)             | false    |              |                                                                                             |
| `node_info`             | [derp.ServerInfoMessage](#derpserverinfomessage) | false    |              |                                                                                             |
| `round_trip_ping`       | string                                           | false    |              |                                                                                             |
| `round_trip_ping_ms`    | integer                                          | false    |              |                                                                                             |
| `severity`              | [health.Severity](#healthseverity)               | false    |              |                                                                                             |
| `stun`                  | [healthsdk.STUNReport](#healthsdkstunreport)     | false    |              |                                                                                             |
| `uses_websocket`        | boolean                                          | false    |              |                                                                                             |
| `warnings`              | array of [health.Message](#healthmessage)        | false    |              |                                                                                             |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## healthsdk.DERPRegionReport

```json
{
  "error": "string",
  "healthy": true,
  "node_reports": [
    {
      "can_exchange_messages": true,
      "client_errs": [
        [
          "string"
        ]
      ],
      "client_logs": [
        [
          "string"
        ]
      ],
      "error": "string",
      "healthy": true,
      "node": {
        "canPort80": true,
        "certName": "string",
        "derpport": 0,
        "forceHTTP": true,
        "hostName": "string",
        "insecureForTests": true,
        "ipv4": "string",
        "ipv6": "string",
        "name": "string",
        "regionID": 0,
        "stunonly": true,
        "stunport": 0,
        "stuntestIP": "string"
      },
      "node_info": {
        "tokenBucketBytesBurst": 0,
        "tokenBucketBytesPerSecond": 0
      },
      "round_trip_ping": "string",
      "round_trip_ping_ms": 0,
      "severity": "ok",
      "stun": {
        "canSTUN": true,
        "enabled": true,
        "error": "string"
      },
      "uses_websocket": true,
      "warnings": [
        {
          "code": "EUNKNOWN",
          "message": "string"
        }
      ]
    }
  ],
  "region": {
    "avoid": true,
    "embeddedRelay": true,
    "nodes": [
      {
        "canPort80": true,
        "certName": "string",
        "derpport": 0,
        "forceHTTP": true,
        "hostName": "string",
        "insecureForTests": true,
        "ipv4": "string",
        "ipv6": "string",
        "name": "string",
        "regionID": 0,
        "stunonly": true,
        "stunport": 0,
        "stuntestIP": "string"
      }
    ],
    "regionCode": "string",
    "regionID": 0,
    "regionName": "string"
  },
  "severity": "ok",
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ]
}
```

### Properties

| Name           | Type                                                          | Required | Restrictions | Description                                                                                 |
|----------------|---------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------|
| `error`        | string                                                        | false    |              |                                                                                             |
| `healthy`      | boolean                                                       | false    |              | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
| `node_reports` | array of [healthsdk.DERPNodeReport](#healthsdkderpnodereport) | false    |              |                                                                                             |
| `region`       | [tailcfg.DERPRegion](#tailcfgderpregion)                      | false    |              |                                                                                             |
| `severity`     | [health.Severity](#healthseverity)                            | false    |              |                                                                                             |
| `warnings`     | array of [health.Message](#healthmessage)                     | false    |              |                                                                                             |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## healthsdk.DatabaseReport

```json
{
  "dismissed": true,
  "error": "string",
  "healthy": true,
  "latency": "string",
  "latency_ms": 0,
  "reachable": true,
  "severity": "ok",
  "threshold_ms": 0,
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ]
}
```

### Properties

| Name           | Type                                      | Required | Restrictions | Description                                                                                 |
|----------------|-------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------|
| `dismissed`    | boolean                                   | false    |              |                                                                                             |
| `error`        | string                                    | false    |              |                                                                                             |
| `healthy`      | boolean                                   | false    |              | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
| `latency`      | string                                    | false    |              |                                                                                             |
| `latency_ms`   | integer                                   | false    |              |                                                                                             |
| `reachable`    | boolean                                   | false    |              |                                                                                             |
| `severity`     | [health.Severity](#healthseverity)        | false    |              |                                                                                             |
| `threshold_ms` | integer                                   | false    |              |                                                                                             |
| `warnings`     | array of [health.Message](#healthmessage) | false    |              |                                                                                             |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## healthsdk.HealthSection

```json
"DERP"
```

### Properties

#### Enumerated Values

| Value(s)                                                                             |
|--------------------------------------------------------------------------------------|
| `AccessURL`, `DERP`, `Database`, `ProvisionerDaemons`, `Websocket`, `WorkspaceProxy` |

## healthsdk.HealthSettings

```json
{
  "dismissed_healthchecks": [
    "DERP"
  ]
}
```

### Properties

| Name                     | Type                                                        | Required | Restrictions | Description |
|--------------------------|-------------------------------------------------------------|----------|--------------|-------------|
| `dismissed_healthchecks` | array of [healthsdk.HealthSection](#healthsdkhealthsection) | false    |              |             |

## healthsdk.HealthcheckReport

```json
{
  "access_url": {
    "access_url": "string",
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "healthz_response": "string",
    "reachable": true,
    "severity": "ok",
    "status_code": 0,
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "coder_version": "string",
  "database": {
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "latency": "string",
    "latency_ms": 0,
    "reachable": true,
    "severity": "ok",
    "threshold_ms": 0,
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "derp": {
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "netcheck": {
      "captivePortal": "string",
      "globalV4": "string",
      "globalV6": "string",
      "icmpv4": true,
      "ipv4": true,
      "ipv4CanSend": true,
      "ipv6": true,
      "ipv6CanSend": true,
      "mappingVariesByDestIP": "string",
      "oshasIPv6": true,
      "pcp": "string",
      "pmp": "string",
      "preferredDERP": 0,
      "regionLatency": {
        "property1": 0,
        "property2": 0
      },
      "regionV4Latency": {
        "property1": 0,
        "property2": 0
      },
      "regionV6Latency": {
        "property1": 0,
        "property2": 0
      },
      "udp": true,
      "upnP": "string"
    },
    "netcheck_err": "string",
    "netcheck_logs": [
      "string"
    ],
    "regions": {
      "property1": {
        "error": "string",
        "healthy": true,
        "node_reports": [
          {
            "can_exchange_messages": true,
            "client_errs": [
              [
                "string"
              ]
            ],
            "client_logs": [
              [
                "string"
              ]
            ],
            "error": "string",
            "healthy": true,
            "node": {
              "canPort80": true,
              "certName": "string",
              "derpport": 0,
              "forceHTTP": true,
              "hostName": "string",
              "insecureForTests": true,
              "ipv4": "string",
              "ipv6": "string",
              "name": "string",
              "regionID": 0,
              "stunonly": true,
              "stunport": 0,
              "stuntestIP": "string"
            },
            "node_info": {
              "tokenBucketBytesBurst": 0,
              "tokenBucketBytesPerSecond": 0
            },
            "round_trip_ping": "string",
            "round_trip_ping_ms": 0,
            "severity": "ok",
            "stun": {
              "canSTUN": true,
              "enabled": true,
              "error": "string"
            },
            "uses_websocket": true,
            "warnings": [
              {
                "code": "EUNKNOWN",
                "message": "string"
              }
            ]
          }
        ],
        "region": {
          "avoid": true,
          "embeddedRelay": true,
          "nodes": [
            {
              "canPort80": true,
              "certName": "string",
              "derpport": 0,
              "forceHTTP": true,
              "hostName": "string",
              "insecureForTests": true,
              "ipv4": "string",
              "ipv6": "string",
              "name": "string",
              "regionID": 0,
              "stunonly": true,
              "stunport": 0,
              "stuntestIP": "string"
            }
          ],
          "regionCode": "string",
          "regionID": 0,
          "regionName": "string"
        },
        "severity": "ok",
        "warnings": [
          {
            "code": "EUNKNOWN",
            "message": "string"
          }
        ]
      },
      "property2": {
        "error": "string",
        "healthy": true,
        "node_reports": [
          {
            "can_exchange_messages": true,
            "client_errs": [
              [
                "string"
              ]
            ],
            "client_logs": [
              [
                "string"
              ]
            ],
            "error": "string",
            "healthy": true,
            "node": {
              "canPort80": true,
              "certName": "string",
              "derpport": 0,
              "forceHTTP": true,
              "hostName": "string",
              "insecureForTests": true,
              "ipv4": "string",
              "ipv6": "string",
              "name": "string",
              "regionID": 0,
              "stunonly": true,
              "stunport": 0,
              "stuntestIP": "string"
            },
            "node_info": {
              "tokenBucketBytesBurst": 0,
              "tokenBucketBytesPerSecond": 0
            },
            "round_trip_ping": "string",
            "round_trip_ping_ms": 0,
            "severity": "ok",
            "stun": {
              "canSTUN": true,
              "enabled": true,
              "error": "string"
            },
            "uses_websocket": true,
            "warnings": [
              {
                "code": "EUNKNOWN",
                "message": "string"
              }
            ]
          }
        ],
        "region": {
          "avoid": true,
          "embeddedRelay": true,
          "nodes": [
            {
              "canPort80": true,
              "certName": "string",
              "derpport": 0,
              "forceHTTP": true,
              "hostName": "string",
              "insecureForTests": true,
              "ipv4": "string",
              "ipv6": "string",
              "name": "string",
              "regionID": 0,
              "stunonly": true,
              "stunport": 0,
              "stuntestIP": "string"
            }
          ],
          "regionCode": "string",
          "regionID": 0,
          "regionName": "string"
        },
        "severity": "ok",
        "warnings": [
          {
            "code": "EUNKNOWN",
            "message": "string"
          }
        ]
      }
    },
    "severity": "ok",
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "healthy": true,
  "provisioner_daemons": {
    "dismissed": true,
    "error": "string",
    "items": [
      {
        "provisioner_daemon": {
          "api_version": "string",
          "created_at": "2019-08-24T14:15:22Z",
          "current_job": {
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "status": "pending",
            "template_display_name": "string",
            "template_icon": "string",
            "template_name": "string"
          },
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
          "key_name": "string",
          "last_seen_at": "2019-08-24T14:15:22Z",
          "name": "string",
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "previous_job": {
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "status": "pending",
            "template_display_name": "string",
            "template_icon": "string",
            "template_name": "string"
          },
          "provisioners": [
            "string"
          ],
          "status": "offline",
          "tags": {
            "property1": "string",
            "property2": "string"
          },
          "version": "string"
        },
        "warnings": [
          {
            "code": "EUNKNOWN",
            "message": "string"
          }
        ]
      }
    ],
    "severity": "ok",
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "severity": "ok",
  "time": "2019-08-24T14:15:22Z",
  "websocket": {
    "body": "string",
    "code": 0,
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "severity": "ok",
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ]
  },
  "workspace_proxy": {
    "dismissed": true,
    "error": "string",
    "healthy": true,
    "severity": "ok",
    "warnings": [
      {
        "code": "EUNKNOWN",
        "message": "string"
      }
    ],
    "workspace_proxies": {
      "regions": [
        {
          "created_at": "2019-08-24T14:15:22Z",
          "deleted": true,
          "derp_enabled": true,
          "derp_only": true,
          "display_name": "string",
          "healthy": true,
          "icon_url": "string",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "name": "string",
          "path_app_url": "string",
          "status": {
            "checked_at": "2019-08-24T14:15:22Z",
            "report": {
              "errors": [
                "string"
              ],
              "warnings": [
                "string"
              ]
            },
            "status": "ok"
          },
          "updated_at": "2019-08-24T14:15:22Z",
          "version": "string",
          "wildcard_hostname": "string"
        }
      ]
    }
  }
}
```

### Properties

| Name                  | Type                                                                     | Required | Restrictions | Description                                                                         |
|-----------------------|--------------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------|
| `access_url`          | [healthsdk.AccessURLReport](#healthsdkaccessurlreport)                   | false    |              |                                                                                     |
| `coder_version`       | string                                                                   | false    |              | The Coder version of the server that the report was generated on.                   |
| `database`            | [healthsdk.DatabaseReport](#healthsdkdatabasereport)                     | false    |              |                                                                                     |
| `derp`                | [healthsdk.DERPHealthReport](#healthsdkderphealthreport)                 | false    |              |                                                                                     |
| `healthy`             | boolean                                                                  | false    |              | Healthy is true if the report returns no errors. Deprecated: use `Severity` instead |
| `provisioner_daemons` | [healthsdk.ProvisionerDaemonsReport](#healthsdkprovisionerdaemonsreport) | false    |              |                                                                                     |
| `severity`            | [health.Severity](#healthseverity)                                       | false    |              | Severity indicates the status of Coder health.                                      |
| `time`                | string                                                                   | false    |              | Time is the time the report was generated at.                                       |
| `websocket`           | [healthsdk.WebsocketReport](#healthsdkwebsocketreport)                   | false    |              |                                                                                     |
| `workspace_proxy`     | [healthsdk.WorkspaceProxyReport](#healthsdkworkspaceproxyreport)         | false    |              |                                                                                     |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## healthsdk.ProvisionerDaemonsReport

```json
{
  "dismissed": true,
  "error": "string",
  "items": [
    {
      "provisioner_daemon": {
        "api_version": "string",
        "created_at": "2019-08-24T14:15:22Z",
        "current_job": {
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "status": "pending",
          "template_display_name": "string",
          "template_icon": "string",
          "template_name": "string"
        },
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
        "key_name": "string",
        "last_seen_at": "2019-08-24T14:15:22Z",
        "name": "string",
        "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
        "previous_job": {
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "status": "pending",
          "template_display_name": "string",
          "template_icon": "string",
          "template_name": "string"
        },
        "provisioners": [
          "string"
        ],
        "status": "offline",
        "tags": {
          "property1": "string",
          "property2": "string"
        },
        "version": "string"
      },
      "warnings": [
        {
          "code": "EUNKNOWN",
          "message": "string"
        }
      ]
    }
  ],
  "severity": "ok",
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ]
}
```

### Properties

| Name        | Type                                                                                      | Required | Restrictions | Description |
|-------------|-------------------------------------------------------------------------------------------|----------|--------------|-------------|
| `dismissed` | boolean                                                                                   | false    |              |             |
| `error`     | string                                                                                    | false    |              |             |
| `items`     | array of [healthsdk.ProvisionerDaemonsReportItem](#healthsdkprovisionerdaemonsreportitem) | false    |              |             |
| `severity`  | [health.Severity](#healthseverity)                                                        | false    |              |             |
| `warnings`  | array of [health.Message](#healthmessage)                                                 | false    |              |             |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## healthsdk.ProvisionerDaemonsReportItem

```json
{
  "provisioner_daemon": {
    "api_version": "string",
    "created_at": "2019-08-24T14:15:22Z",
    "current_job": {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "status": "pending",
      "template_display_name": "string",
      "template_icon": "string",
      "template_name": "string"
    },
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "key_id": "1e779c8a-6786-4c89-b7c3-a6666f5fd6b5",
    "key_name": "string",
    "last_seen_at": "2019-08-24T14:15:22Z",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "previous_job": {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "status": "pending",
      "template_display_name": "string",
      "template_icon": "string",
      "template_name": "string"
    },
    "provisioners": [
      "string"
    ],
    "status": "offline",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "version": "string"
  },
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ]
}
```

### Properties

| Name                 | Type                                                     | Required | Restrictions | Description |
|----------------------|----------------------------------------------------------|----------|--------------|-------------|
| `provisioner_daemon` | [codersdk.ProvisionerDaemon](#codersdkprovisionerdaemon) | false    |              |             |
| `warnings`           | array of [health.Message](#healthmessage)                | false    |              |             |

## healthsdk.STUNReport

```json
{
  "canSTUN": true,
  "enabled": true,
  "error": "string"
}
```

### Properties

| Name      | Type    | Required | Restrictions | Description |
|-----------|---------|----------|--------------|-------------|
| `canSTUN` | boolean | false    |              |             |
| `enabled` | boolean | false    |              |             |
| `error`   | string  | false    |              |             |

## healthsdk.UpdateHealthSettings

```json
{
  "dismissed_healthchecks": [
    "DERP"
  ]
}
```

### Properties

| Name                     | Type                                                        | Required | Restrictions | Description |
|--------------------------|-------------------------------------------------------------|----------|--------------|-------------|
| `dismissed_healthchecks` | array of [healthsdk.HealthSection](#healthsdkhealthsection) | false    |              |             |

## healthsdk.WebsocketReport

```json
{
  "body": "string",
  "code": 0,
  "dismissed": true,
  "error": "string",
  "healthy": true,
  "severity": "ok",
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ]
}
```

### Properties

| Name        | Type                                      | Required | Restrictions | Description                                                                                 |
|-------------|-------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------|
| `body`      | string                                    | false    |              |                                                                                             |
| `code`      | integer                                   | false    |              |                                                                                             |
| `dismissed` | boolean                                   | false    |              |                                                                                             |
| `error`     | string                                    | false    |              |                                                                                             |
| `healthy`   | boolean                                   | false    |              | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
| `severity`  | [health.Severity](#healthseverity)        | false    |              |                                                                                             |
| `warnings`  | array of [health.Message](#healthmessage) | false    |              |                                                                                             |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## healthsdk.WorkspaceProxyReport

```json
{
  "dismissed": true,
  "error": "string",
  "healthy": true,
  "severity": "ok",
  "warnings": [
    {
      "code": "EUNKNOWN",
      "message": "string"
    }
  ],
  "workspace_proxies": {
    "regions": [
      {
        "created_at": "2019-08-24T14:15:22Z",
        "deleted": true,
        "derp_enabled": true,
        "derp_only": true,
        "display_name": "string",
        "healthy": true,
        "icon_url": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "name": "string",
        "path_app_url": "string",
        "status": {
          "checked_at": "2019-08-24T14:15:22Z",
          "report": {
            "errors": [
              "string"
            ],
            "warnings": [
              "string"
            ]
          },
          "status": "ok"
        },
        "updated_at": "2019-08-24T14:15:22Z",
        "version": "string",
        "wildcard_hostname": "string"
      }
    ]
  }
}
```

### Properties

| Name                | Type                                                                                                 | Required | Restrictions | Description                                                                                 |
|---------------------|------------------------------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------|
| `dismissed`         | boolean                                                                                              | false    |              |                                                                                             |
| `error`             | string                                                                                               | false    |              |                                                                                             |
| `healthy`           | boolean                                                                                              | false    |              | Healthy is deprecated and left for backward compatibility purposes, use `Severity` instead. |
| `severity`          | [health.Severity](#healthseverity)                                                                   | false    |              |                                                                                             |
| `warnings`          | array of [health.Message](#healthmessage)                                                            | false    |              |                                                                                             |
| `workspace_proxies` | [codersdk.RegionsResponse-codersdk_WorkspaceProxy](#codersdkregionsresponse-codersdk_workspaceproxy) | false    |              |                                                                                             |

#### Enumerated Values

| Property   | Value(s)                 |
|------------|--------------------------|
| `severity` | `error`, `ok`, `warning` |

## key.NodePublic

```json
{}
```

### Properties

None

## legacyscim.SCIMUser

```json
{
  "active": true,
  "emails": [
    {
      "display": "string",
      "primary": true,
      "type": "string",
      "value": "user@example.com"
    }
  ],
  "groups": [
    null
  ],
  "id": "string",
  "meta": {
    "resourceType": "string"
  },
  "name": {
    "familyName": "string",
    "givenName": "string"
  },
  "schemas": [
    "string"
  ],
  "userName": "string"
}
```

### Properties

| Name             | Type               | Required | Restrictions | Description                                                                 |
|------------------|--------------------|----------|--------------|-----------------------------------------------------------------------------|
| `active`         | boolean            | false    |              | Active is a ptr to prevent the empty value from being interpreted as false. |
| `emails`         | array of object    | false    |              |                                                                             |
| `» display`      | string             | false    |              |                                                                             |
| `» primary`      | boolean            | false    |              |                                                                             |
| `» type`         | string             | false    |              |                                                                             |
| `» value`        | string             | false    |              |                                                                             |
| `groups`         | array of undefined | false    |              |                                                                             |
| `id`             | string             | false    |              |                                                                             |
| `meta`           | object             | false    |              |                                                                             |
| `» resourceType` | string             | false    |              |                                                                             |
| `name`           | object             | false    |              |                                                                             |
| `» familyName`   | string             | false    |              |                                                                             |
| `» givenName`    | string             | false    |              |                                                                             |
| `schemas`        | array of string    | false    |              |                                                                             |
| `userName`       | string             | false    |              |                                                                             |

## netcheck.Report

```json
{
  "captivePortal": "string",
  "globalV4": "string",
  "globalV6": "string",
  "icmpv4": true,
  "ipv4": true,
  "ipv4CanSend": true,
  "ipv6": true,
  "ipv6CanSend": true,
  "mappingVariesByDestIP": "string",
  "oshasIPv6": true,
  "pcp": "string",
  "pmp": "string",
  "preferredDERP": 0,
  "regionLatency": {
    "property1": 0,
    "property2": 0
  },
  "regionV4Latency": {
    "property1": 0,
    "property2": 0
  },
  "regionV6Latency": {
    "property1": 0,
    "property2": 0
  },
  "udp": true,
  "upnP": "string"
}
```

### Properties

| Name                    | Type    | Required | Restrictions | Description                                                                                         |
|-------------------------|---------|----------|--------------|-----------------------------------------------------------------------------------------------------|
| `captivePortal`         | string  | false    |              | Captiveportal is set when we think there's a captive portal that is intercepting HTTP traffic.      |
| `globalV4`              | string  | false    |              | ip:port of global IPv4                                                                              |
| `globalV6`              | string  | false    |              | [ip]:port of global IPv6                                                                            |
| `icmpv4`                | boolean | false    |              | an ICMPv4 round trip completed                                                                      |
| `ipv4`                  | boolean | false    |              | an IPv4 STUN round trip completed                                                                   |
| `ipv4CanSend`           | boolean | false    |              | an IPv4 packet was able to be sent                                                                  |
| `ipv6`                  | boolean | false    |              | an IPv6 STUN round trip completed                                                                   |
| `ipv6CanSend`           | boolean | false    |              | an IPv6 packet was able to be sent                                                                  |
| `mappingVariesByDestIP` | string  | false    |              | Mappingvariesbydestip is whether STUN results depend which STUN server you're talking to (on IPv4). |
| `oshasIPv6`             | boolean | false    |              | could bind a socket to ::1                                                                          |
| `pcp`                   | string  | false    |              | Pcp is whether PCP appears present on the LAN. Empty means not checked.                             |
| `pmp`                   | string  | false    |              | Pmp is whether NAT-PMP appears present on the LAN. Empty means not checked.                         |
| `preferredDERP`         | integer | false    |              | or 0 for unknown                                                                                    |
| `regionLatency`         | object  | false    |              | keyed by DERP Region ID                                                                             |
| » `[any property]`      | integer | false    |              |                                                                                                     |
| `regionV4Latency`       | object  | false    |              | keyed by DERP Region ID                                                                             |
| » `[any property]`      | integer | false    |              |                                                                                                     |
| `regionV6Latency`       | object  | false    |              | keyed by DERP Region ID                                                                             |
| » `[any property]`      | integer | false    |              |                                                                                                     |
| `udp`                   | boolean | false    |              | a UDP STUN round trip completed                                                                     |
| `upnP`                  | string  | false    |              | Upnp is whether UPnP appears present on the LAN. Empty means not checked.                           |

## regexp.Regexp

```json
{}
```

### Properties

None

## serpent.Annotations

```json
{
  "property1": "string",
  "property2": "string"
}
```

### Properties

| Name             | Type   | Required | Restrictions | Description |
|------------------|--------|----------|--------------|-------------|
| `[any property]` | string | false    |              |             |

## serpent.Group

```json
{
  "description": "string",
  "name": "string",
  "parent": {
    "description": "string",
    "name": "string",
    "parent": {},
    "yaml": "string"
  },
  "yaml": "string"
}
```

### Properties

| Name          | Type                           | Required | Restrictions | Description |
|---------------|--------------------------------|----------|--------------|-------------|
| `description` | string                         | false    |              |             |
| `name`        | string                         | false    |              |             |
| `parent`      | [serpent.Group](#serpentgroup) | false    |              |             |
| `yaml`        | string                         | false    |              |             |

## serpent.HostPort

```json
{
  "host": "string",
  "port": "string"
}
```

### Properties

| Name   | Type   | Required | Restrictions | Description |
|--------|--------|----------|--------------|-------------|
| `host` | string | false    |              |             |
| `port` | string | false    |              |             |

## serpent.Option

```json
{
  "annotations": {
    "property1": "string",
    "property2": "string"
  },
  "default": "string",
  "description": "string",
  "env": "string",
  "flag": "string",
  "flag_shorthand": "string",
  "group": {
    "description": "string",
    "name": "string",
    "parent": {
      "description": "string",
      "name": "string",
      "parent": {},
      "yaml": "string"
    },
    "yaml": "string"
  },
  "hidden": true,
  "name": "string",
  "required": true,
  "use_instead": [
    {
      "annotations": {
        "property1": "string",
        "property2": "string"
      },
      "default": "string",
      "description": "string",
      "env": "string",
      "flag": "string",
      "flag_shorthand": "string",
      "group": {
        "description": "string",
        "name": "string",
        "parent": {
          "description": "string",
          "name": "string",
          "parent": {},
          "yaml": "string"
        },
        "yaml": "string"
      },
      "hidden": true,
      "name": "string",
      "required": true,
      "use_instead": [],
      "value": null,
      "value_source": "",
      "yaml": "string"
    }
  ],
  "value": null,
  "value_source": "",
  "yaml": "string"
}
```

### Properties

| Name             | Type                                       | Required | Restrictions | Description                                                                                                                                        |
|------------------|--------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------|
| `annotations`    | [serpent.Annotations](#serpentannotations) | false    |              | Annotations enable extensions to serpent higher up in the stack. It's useful for help formatting and documentation generation.                     |
| `default`        | string                                     | false    |              | Default is parsed into Value if set. Must be `""` if `DefaultFn` != nil                                                                            |
| `description`    | string                                     | false    |              |                                                                                                                                                    |
| `env`            | string                                     | false    |              | Env is the environment variable used to configure this option. If unset, environment configuring is disabled.                                      |
| `flag`           | string                                     | false    |              | Flag is the long name of the flag used to configure this option. If unset, flag configuring is disabled.                                           |
| `flag_shorthand` | string                                     | false    |              | Flag shorthand is the one-character shorthand for the flag. If unset, no shorthand is used.                                                        |
| `group`          | [serpent.Group](#serpentgroup)             | false    |              | Group is a group hierarchy that helps organize this option in help, configs and other documentation.                                               |
| `hidden`         | boolean                                    | false    |              |                                                                                                                                                    |
| `name`           | string                                     | false    |              |                                                                                                                                                    |
| `required`       | boolean                                    | false    |              | Required means this value must be set by some means. It requires `ValueSource != ValueSourceNone` If `Default` is set, then `Required` is ignored. |
| `use_instead`    | array of [serpent.Option](#serpentoption)  | false    |              | Use instead is a list of options that should be used instead of this one. The field is used to generate a deprecation warning.                     |
| `value`          | any                                        | false    |              | Value includes the types listed in values.go.                                                                                                      |
| `value_source`   | [serpent.ValueSource](#serpentvaluesource) | false    |              |                                                                                                                                                    |
| `yaml`           | string                                     | false    |              | Yaml is the YAML key used to configure this option. If unset, YAML configuring is disabled.                                                        |

## serpent.Regexp

```json
{}
```

### Properties

None

## serpent.Struct-array_codersdk_ExternalAuthConfig

```json
{
  "value": [
    {
      "api_base_url": "string",
      "app_install_url": "string",
      "app_installations_url": "string",
      "auth_url": "string",
      "client_id": "string",
      "code_challenge_methods_supported": [
        "string"
      ],
      "device_code_url": "string",
      "device_flow": true,
      "display_icon": "string",
      "display_name": "string",
      "id": "string",
      "mcp_tool_allow_regex": "string",
      "mcp_tool_deny_regex": "string",
      "mcp_url": "string",
      "no_refresh": true,
      "redirect_url": "string",
      "regex": "string",
      "revoke_url": "string",
      "scopes": [
        "string"
      ],
      "token_url": "string",
      "type": "string",
      "validate_url": "string"
    }
  ]
}
```

### Properties

| Name    | Type                                                                | Required | Restrictions | Description |
|---------|---------------------------------------------------------------------|----------|--------------|-------------|
| `value` | array of [codersdk.ExternalAuthConfig](#codersdkexternalauthconfig) | false    |              |             |

## serpent.Struct-array_codersdk_LinkConfig

```json
{
  "value": [
    {
      "icon": "bug",
      "location": "navbar",
      "name": "string",
      "target": "string"
    }
  ]
}
```

### Properties

| Name    | Type                                                | Required | Restrictions | Description |
|---------|-----------------------------------------------------|----------|--------------|-------------|
| `value` | array of [codersdk.LinkConfig](#codersdklinkconfig) | false    |              |             |

## serpent.URL

```json
{
  "forceQuery": true,
  "fragment": "string",
  "host": "string",
  "omitHost": true,
  "opaque": "string",
  "path": "string",
  "rawFragment": "string",
  "rawPath": "string",
  "rawQuery": "string",
  "scheme": "string",
  "user": {}
}
```

### Properties

| Name         | Type    | Required | Restrictions | Description                                                                                                                                                            |
|--------------|---------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `forceQuery` | boolean | false    |              | Forcequery indicates whether the original URL contained a query ('?') character. When set, the String method will include a trailing '?', even when RawQuery is empty. |
| `fragment`   | string  | false    |              | fragment for references (without '#')                                                                                                                                  |
| `host`       | string  | false    |              | "host" or "host:port" (see Hostname and Port methods)                                                                                                                  |
| `omitHost`   | boolean | false    |              | Omithost indicates the URL has an empty host (authority). When set, the String method will not include the host when it is empty.                                      |
| `opaque`     | string  | false    |              | encoded opaque data                                                                                                                                                    |
| `path`       | string  | false    |              | path (relative paths may omit leading slash)                                                                                                                           |
|`rawFragment`|string|false||Rawfragment is an optional field containing an encoded fragment hint. See the EscapedFragment method for more details.
In general, code should call EscapedFragment instead of reading RawFragment.|
|`rawPath`|string|false||Rawpath is an optional field containing an encoded path hint. See the EscapedPath method for more details.
In general, code should call EscapedPath instead of reading RawPath.|
|`rawQuery`|string|false||Rawquery contains the encoded query values, without the initial '?'. Use URL.Query to decode the query.|
|`scheme`|string|false|||
|`user`|[url.Userinfo](#urluserinfo)|false||username and password information|

## serpent.ValueSource

```json
""
```

### Properties

#### Enumerated Values

| Value(s)                             |
|--------------------------------------|
| ``, `default`, `env`, `flag`, `yaml` |

## tailcfg.DERPHomeParams

```json
{
  "regionScore": {
    "property1": 0,
    "property2": 0
  }
}
```

### Properties

|Name|Type|Required|Restrictions|Description|
|---|---|---|---|---|
|`regionScore`|object|false||Regionscore scales latencies of DERP regions by a given scaling factor when determining which region to use as the home ("preferred") DERP. Scores in the range (0, 1) will cause this region to be proportionally more preferred, and scores in the range (1, ∞) will penalize a region.
If a region is not present in this map, it is treated as having a score of 1.0.
Scores should not be 0 or negative; such scores will be ignored.
A nil map means no change from the previous value (if any); an empty non-nil map can be sent to reset all scores back to 1.0.|
|» `[any property]`|number|false|||

## tailcfg.DERPMap

```json
{
  "homeParams": {
    "regionScore": {
      "property1": 0,
      "property2": 0
    }
  },
  "omitDefaultRegions": true,
  "regions": {
    "property1": {
      "avoid": true,
      "embeddedRelay": true,
      "nodes": [
        {
          "canPort80": true,
          "certName": "string",
          "derpport": 0,
          "forceHTTP": true,
          "hostName": "string",
          "insecureForTests": true,
          "ipv4": "string",
          "ipv6": "string",
          "name": "string",
          "regionID": 0,
          "stunonly": true,
          "stunport": 0,
          "stuntestIP": "string"
        }
      ],
      "regionCode": "string",
      "regionID": 0,
      "regionName": "string"
    },
    "property2": {
      "avoid": true,
      "embeddedRelay": true,
      "nodes": [
        {
          "canPort80": true,
          "certName": "string",
          "derpport": 0,
          "forceHTTP": true,
          "hostName": "string",
          "insecureForTests": true,
          "ipv4": "string",
          "ipv6": "string",
          "name": "string",
          "regionID": 0,
          "stunonly": true,
          "stunport": 0,
          "stuntestIP": "string"
        }
      ],
      "regionCode": "string",
      "regionID": 0,
      "regionName": "string"
    }
  }
}
```

### Properties

|Name|Type|Required|Restrictions|Description|
|---|---|---|---|---|
|`homeParams`|[tailcfg.DERPHomeParams](#tailcfgderphomeparams)|false||Homeparams if non-nil, is a change in home parameters.
The rest of the DEPRMap fields, if zero, means unchanged.|
|`omitDefaultRegions`|boolean|false||Omitdefaultregions specifies to not use Tailscale's DERP servers, and only use those specified in this DERPMap. If there are none set outside of the defaults, this is a noop.
This field is only meaningful if the Regions map is non-nil (indicating a change).|
|`regions`|object|false||Regions is the set of geographic regions running DERP node(s).
It's keyed by the DERPRegion.RegionID.
The numbers are not necessarily contiguous.|
|» `[any property]`|[tailcfg.DERPRegion](#tailcfgderpregion)|false|||

## tailcfg.DERPNode

```json
{
  "canPort80": true,
  "certName": "string",
  "derpport": 0,
  "forceHTTP": true,
  "hostName": "string",
  "insecureForTests": true,
  "ipv4": "string",
  "ipv6": "string",
  "name": "string",
  "regionID": 0,
  "stunonly": true,
  "stunport": 0,
  "stuntestIP": "string"
}
```

### Properties

| Name        | Type    | Required | Restrictions | Description                                                                                                                                                                                                     |
|-------------|---------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `canPort80` | boolean | false    |              | Canport80 specifies whether this DERP node is accessible over HTTP on port 80 specifically. This is used for captive portal checks.                                                                             |
| `certName`  | string  | false    |              | Certname optionally specifies the expected TLS cert common name. If empty, HostName is used. If CertName is non-empty, HostName is only used for the TCP dial (if IPv4/IPv6 are not present) + TLS ClientHello. |
|`derpport`|integer|false||Derpport optionally provides an alternate TLS port number for the DERP HTTPS server.
If zero, 443 is used.|
|`forceHTTP`|boolean|false||Forcehttp is used by unit tests to force HTTP. It should not be set by users.|
|`hostName`|string|false||Hostname is the DERP node's hostname.
It is required but need not be unique; multiple nodes may have the same HostName but vary in configuration otherwise.|
|`insecureForTests`|boolean|false||Insecurefortests is used by unit tests to disable TLS verification. It should not be set by users.|
|`ipv4`|string|false||Ipv4 optionally forces an IPv4 address to use, instead of using DNS. If empty, A record(s) from DNS lookups of HostName are used. If the string is not an IPv4 address, IPv4 is not used; the conventional string to disable IPv4 (and not use DNS) is "none".|
|`ipv6`|string|false||Ipv6 optionally forces an IPv6 address to use, instead of using DNS. If empty, AAAA record(s) from DNS lookups of HostName are used. If the string is not an IPv6 address, IPv6 is not used; the conventional string to disable IPv6 (and not use DNS) is "none".|
|`name`|string|false||Name is a unique node name (across all regions). It is not a host name. It's typically of the form "1b", "2a", "3b", etc. (region ID + suffix within that region)|
|`regionID`|integer|false||Regionid is the RegionID of the DERPRegion that this node is running in.|
|`stunonly`|boolean|false||Stunonly marks a node as only a STUN server and not a DERP server.|
|`stunport`|integer|false||Port optionally specifies a STUN port to use. Zero means 3478. To disable STUN on this node, use -1.|
|`stuntestIP`|string|false||Stuntestip is used in tests to override the STUN server's IP. If empty, it's assumed to be the same as the DERP server.|

## tailcfg.DERPRegion

```json
{
  "avoid": true,
  "embeddedRelay": true,
  "nodes": [
    {
      "canPort80": true,
      "certName": "string",
      "derpport": 0,
      "forceHTTP": true,
      "hostName": "string",
      "insecureForTests": true,
      "ipv4": "string",
      "ipv6": "string",
      "name": "string",
      "regionID": 0,
      "stunonly": true,
      "stunport": 0,
      "stuntestIP": "string"
    }
  ],
  "regionCode": "string",
  "regionID": 0,
  "regionName": "string"
}
```

### Properties

| Name            | Type    | Required | Restrictions | Description                                                                                                                                                                                                                         |
|-----------------|---------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `avoid`         | boolean | false    |              | Avoid is whether the client should avoid picking this as its home region. The region should only be used if a peer is there. Clients already using this region as their home should migrate away to a new region without Avoid set. |
| `embeddedRelay` | boolean | false    |              | Embeddedrelay is true when the region is bundled with the Coder control plane.                                                                                                                                                      |
|`nodes`|array of [tailcfg.DERPNode](#tailcfgderpnode)|false||Nodes are the DERP nodes running in this region, in priority order for the current client. Client TLS connections should ideally only go to the first entry (falling back to the second if necessary). STUN packets should go to the first 1 or 2.
If nodes within a region route packets amongst themselves, but not to other regions. That said, each user/domain should get a the same preferred node order, so if all nodes for a user/network pick the first one (as they should, when things are healthy), the inter-cluster routing is minimal to zero.|
|`regionCode`|string|false||Regioncode is a short name for the region. It's usually a popular city or airport code in the region: "nyc", "sf", "sin", "fra", etc.|
|`regionID`|integer|false||Regionid is a unique integer for a geographic region.
It corresponds to the legacy derpN.tailscale.com hostnames used by older clients. (Older clients will continue to resolve derpN.tailscale.com when contacting peers, rather than use the server-provided DERPMap)
RegionIDs must be non-zero, positive, and guaranteed to fit in a JavaScript number.
RegionIDs in range 900-999 are reserved for end users to run their own DERP nodes.|
|`regionName`|string|false||Regionname is a long English name for the region: "New York City", "San Francisco", "Singapore", "Frankfurt", etc.|

## url.Userinfo

```json
{}
```

### Properties

None

## workspaceapps.AccessMethod

```json
"path"
```

### Properties

#### Enumerated Values

| Value(s)                        |
|---------------------------------|
| `path`, `subdomain`, `terminal` |

## workspaceapps.IssueTokenRequest

```json
{
  "app_hostname": "string",
  "app_path": "string",
  "app_query": "string",
  "app_request": {
    "access_method": "path",
    "agent_name_or_id": "string",
    "app_prefix": "string",
    "app_slug_or_port": "string",
    "base_path": "string",
    "username_or_id": "string",
    "workspace_name_or_id": "string"
  },
  "path_app_base_url": "string",
  "session_token": "string"
}
```

### Properties

| Name                | Type                                           | Required | Restrictions | Description                                                                                                     |
|---------------------|------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------|
| `app_hostname`      | string                                         | false    |              | App hostname is the optional hostname for subdomain apps on the external proxy. It must start with an asterisk. |
| `app_path`          | string                                         | false    |              | App path is the path of the user underneath the app base path.                                                  |
| `app_query`         | string                                         | false    |              | App query is the query parameters the user provided in the app request.                                         |
| `app_request`       | [workspaceapps.Request](#workspaceappsrequest) | false    |              |                                                                                                                 |
| `path_app_base_url` | string                                         | false    |              | Path app base URL is required.                                                                                  |
| `session_token`     | string                                         | false    |              | Session token is the session token provided by the user.                                                        |

## workspaceapps.Request

```json
{
  "access_method": "path",
  "agent_name_or_id": "string",
  "app_prefix": "string",
  "app_slug_or_port": "string",
  "base_path": "string",
  "username_or_id": "string",
  "workspace_name_or_id": "string"
}
```

### Properties

| Name                   | Type                                                     | Required | Restrictions | Description                                                                                                                                                                           |
|------------------------|----------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `access_method`        | [workspaceapps.AccessMethod](#workspaceappsaccessmethod) | false    |              |                                                                                                                                                                                       |
| `agent_name_or_id`     | string                                                   | false    |              | Agent name or ID is not required if the workspace has only one agent.                                                                                                                 |
| `app_prefix`           | string                                                   | false    |              | Prefix is the prefix of the subdomain app URL. Prefix should have a trailing "---" if set.                                                                                            |
| `app_slug_or_port`     | string                                                   | false    |              |                                                                                                                                                                                       |
| `base_path`            | string                                                   | false    |              | Base path of the app. For path apps, this is the path prefix in the router for this particular app. For subdomain apps, this should be "/". This is used for setting the cookie path. |
| `username_or_id`       | string                                                   | false    |              | For the following fields, if the AccessMethod is AccessMethodTerminal, then only AgentNameOrID may be set and it must be a UUID. The other fields must be left blank.                 |
| `workspace_name_or_id` | string                                                   | false    |              |                                                                                                                                                                                       |

## workspaceapps.StatsReport

```json
{
  "access_method": "path",
  "agent_id": "string",
  "requests": 0,
  "session_ended_at": "string",
  "session_id": "string",
  "session_started_at": "string",
  "slug_or_port": "string",
  "user_id": "string",
  "workspace_id": "string"
}
```

### Properties

| Name                 | Type                                                     | Required | Restrictions | Description                                                                             |
|----------------------|----------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------|
| `access_method`      | [workspaceapps.AccessMethod](#workspaceappsaccessmethod) | false    |              |                                                                                         |
| `agent_id`           | string                                                   | false    |              |                                                                                         |
| `requests`           | integer                                                  | false    |              |                                                                                         |
| `session_ended_at`   | string                                                   | false    |              | Updated periodically while app is in use active and when the last connection is closed. |
| `session_id`         | string                                                   | false    |              |                                                                                         |
| `session_started_at` | string                                                   | false    |              |                                                                                         |
| `slug_or_port`       | string                                                   | false    |              |                                                                                         |
| `user_id`            | string                                                   | false    |              |                                                                                         |
| `workspace_id`       | string                                                   | false    |              |                                                                                         |

## workspacesdk.AgentConnectionInfo

```json
{
  "derp_force_websockets": true,
  "derp_map": {
    "homeParams": {
      "regionScore": {
        "property1": 0,
        "property2": 0
      }
    },
    "omitDefaultRegions": true,
    "regions": {
      "property1": {
        "avoid": true,
        "embeddedRelay": true,
        "nodes": [
          {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          }
        ],
        "regionCode": "string",
        "regionID": 0,
        "regionName": "string"
      },
      "property2": {
        "avoid": true,
        "embeddedRelay": true,
        "nodes": [
          {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          }
        ],
        "regionCode": "string",
        "regionID": 0,
        "regionName": "string"
      }
    }
  },
  "disable_direct_connections": true,
  "hostname_suffix": "string"
}
```

### Properties

| Name                         | Type                               | Required | Restrictions | Description |
|------------------------------|------------------------------------|----------|--------------|-------------|
| `derp_force_websockets`      | boolean                            | false    |              |             |
| `derp_map`                   | [tailcfg.DERPMap](#tailcfgderpmap) | false    |              |             |
| `disable_direct_connections` | boolean                            | false    |              |             |
| `hostname_suffix`            | string                             | false    |              |             |

## workspacesdk.AgentUpdate

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "lifecycle": "created"
}
```

### Properties

| Name        | Type                                                                 | Required | Restrictions | Description |
|-------------|----------------------------------------------------------------------|----------|--------------|-------------|
| `id`        | string                                                               | false    |              |             |
| `lifecycle` | [codersdk.WorkspaceAgentLifecycle](#codersdkworkspaceagentlifecycle) | false    |              |             |

## workspacesdk.BuildUpdate

```json
{
  "job_status": "pending",
  "transition": "start"
}
```

### Properties

| Name         | Type                                                           | Required | Restrictions | Description |
|--------------|----------------------------------------------------------------|----------|--------------|-------------|
| `job_status` | [codersdk.ProvisionerJobStatus](#codersdkprovisionerjobstatus) | false    |              |             |
| `transition` | [codersdk.WorkspaceTransition](#codersdkworkspacetransition)   | false    |              |             |

## workspacesdk.ConnectionWatchEvent

```json
{
  "agent_update": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "lifecycle": "created"
  },
  "build_update": {
    "job_status": "pending",
    "transition": "start"
  },
  "error": {
    "code": 0,
    "details": "string",
    "message": "string",
    "retryable": true
  }
}
```

### Properties

| Name           | Type                                                 | Required | Restrictions | Description |
|----------------|------------------------------------------------------|----------|--------------|-------------|
| `agent_update` | [workspacesdk.AgentUpdate](#workspacesdkagentupdate) | false    |              |             |
| `build_update` | [workspacesdk.BuildUpdate](#workspacesdkbuildupdate) | false    |              |             |
| `error`        | [workspacesdk.WatchError](#workspacesdkwatcherror)   | false    |              |             |

## workspacesdk.WatchError

```json
{
  "code": 0,
  "details": "string",
  "message": "string",
  "retryable": true
}
```

### Properties

| Name        | Type                                                       | Required | Restrictions | Description |
|-------------|------------------------------------------------------------|----------|--------------|-------------|
| `code`      | [workspacesdk.WatchErrorCode](#workspacesdkwatcherrorcode) | false    |              |             |
| `details`   | string                                                     | false    |              |             |
| `message`   | string                                                     | false    |              |             |
| `retryable` | boolean                                                    | false    |              |             |

## workspacesdk.WatchErrorCode

```json
0
```

### Properties

#### Enumerated Values

| Value(s)                          |
|-----------------------------------|
| `0`, `1`, `2`, `3`, `4`, `5`, `6` |

## wsproxysdk.CryptoKeysResponse

```json
{
  "crypto_keys": [
    {
      "deletes_at": "2019-08-24T14:15:22Z",
      "feature": "workspace_apps_api_key",
      "secret": "string",
      "sequence": 0,
      "starts_at": "2019-08-24T14:15:22Z"
    }
  ]
}
```

### Properties

| Name          | Type                                              | Required | Restrictions | Description |
|---------------|---------------------------------------------------|----------|--------------|-------------|
| `crypto_keys` | array of [codersdk.CryptoKey](#codersdkcryptokey) | false    |              |             |

## wsproxysdk.DeregisterWorkspaceProxyRequest

```json
{
  "replica_id": "string"
}
```

### Properties

| Name         | Type   | Required | Restrictions | Description                                                                                                                                                                                       |
|--------------|--------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `replica_id` | string | false    |              | Replica ID is a unique identifier for the replica of the proxy that is deregistering. It should be generated by the client on startup and should've already been passed to the register endpoint. |

## wsproxysdk.IssueSignedAppTokenResponse

```json
{
  "signed_token_str": "string"
}
```

### Properties

| Name               | Type   | Required | Restrictions | Description                                                 |
|--------------------|--------|----------|--------------|-------------------------------------------------------------|
| `signed_token_str` | string | false    |              | Signed token str should be set as a cookie on the response. |

## wsproxysdk.RegisterWorkspaceProxyRequest

```json
{
  "access_url": "string",
  "derp_enabled": true,
  "derp_only": true,
  "hostname": "string",
  "replica_error": "string",
  "replica_id": "string",
  "replica_relay_address": "string",
  "version": "string",
  "wildcard_hostname": "string"
}
```

### Properties

| Name           | Type    | Required | Restrictions | Description                                                                                                                              |
|----------------|---------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------|
| `access_url`   | string  | false    |              | Access URL that hits the workspace proxy api.                                                                                            |
| `derp_enabled` | boolean | false    |              | Derp enabled indicates whether the proxy should be included in the DERP map or not.                                                      |
| `derp_only`    | boolean | false    |              | Derp only indicates whether the proxy should only be included in the DERP map and should not be used for serving apps.                   |
| `hostname`     | string  | false    |              | Hostname is the OS hostname of the machine that the proxy is running on.  This is only used for tracking purposes in the replicas table. |
|`replica_error`|string|false||Replica error is the error that the replica encountered when trying to dial it's peers. This is stored in the replicas table for debugging purposes but does not affect the proxy's ability to register.
This value is only stored on subsequent requests to the register endpoint, not the first request.|
|`replica_id`|string|false||Replica ID is a unique identifier for the replica of the proxy that is registering. It should be generated by the client on startup and persisted (in memory only) until the process is restarted.|
|`replica_relay_address`|string|false||Replica relay address is the DERP address of the replica that other replicas may use to connect internally for DERP meshing.|
|`version`|string|false||Version is the Coder version of the proxy.|
|`wildcard_hostname`|string|false||Wildcard hostname that the workspace proxy api is serving for subdomain apps.|

## wsproxysdk.RegisterWorkspaceProxyResponse

```json
{
  "derp_force_websockets": true,
  "derp_map": {
    "homeParams": {
      "regionScore": {
        "property1": 0,
        "property2": 0
      }
    },
    "omitDefaultRegions": true,
    "regions": {
      "property1": {
        "avoid": true,
        "embeddedRelay": true,
        "nodes": [
          {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          }
        ],
        "regionCode": "string",
        "regionID": 0,
        "regionName": "string"
      },
      "property2": {
        "avoid": true,
        "embeddedRelay": true,
        "nodes": [
          {
            "canPort80": true,
            "certName": "string",
            "derpport": 0,
            "forceHTTP": true,
            "hostName": "string",
            "insecureForTests": true,
            "ipv4": "string",
            "ipv6": "string",
            "name": "string",
            "regionID": 0,
            "stunonly": true,
            "stunport": 0,
            "stuntestIP": "string"
          }
        ],
        "regionCode": "string",
        "regionID": 0,
        "regionName": "string"
      }
    }
  },
  "derp_mesh_key": "string",
  "derp_region_id": 0,
  "sibling_replicas": [
    {
      "created_at": "2019-08-24T14:15:22Z",
      "database_latency": 0,
      "error": "string",
      "hostname": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "region_id": 0,
      "relay_address": "string"
    }
  ]
}
```

### Properties

| Name                    | Type                                          | Required | Restrictions | Description                                                                            |
|-------------------------|-----------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------|
| `derp_force_websockets` | boolean                                       | false    |              |                                                                                        |
| `derp_map`              | [tailcfg.DERPMap](#tailcfgderpmap)            | false    |              |                                                                                        |
| `derp_mesh_key`         | string                                        | false    |              |                                                                                        |
| `derp_region_id`        | integer                                       | false    |              |                                                                                        |
| `sibling_replicas`      | array of [codersdk.Replica](#codersdkreplica) | false    |              | Sibling replicas is a list of all other replicas of the proxy that have not timed out. |

## wsproxysdk.ReportAppStatsRequest

```json
{
  "stats": [
    {
      "access_method": "path",
      "agent_id": "string",
      "requests": 0,
      "session_ended_at": "string",
      "session_id": "string",
      "session_started_at": "string",
      "slug_or_port": "string",
      "user_id": "string",
      "workspace_id": "string"
    }
  ]
}
```

### Properties

| Name    | Type                                                            | Required | Restrictions | Description |
|---------|-----------------------------------------------------------------|----------|--------------|-------------|
| `stats` | array of [workspaceapps.StatsReport](#workspaceappsstatsreport) | false    |              |             |

---

# Secrets

Source: https://coder.com/docs/reference/api/secrets

<!-- DO NOT EDIT | GENERATED CONTENT -->

## List user secrets

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/secrets \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/secrets`

### Parameters

| Name   | In   | Type   | Required | Description              |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true     | User ID, username, or me |

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "description": "string",
    "enabled": true,
    "env_name": "string",
    "file_path": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "updated_at": "2019-08-24T14:15:22Z"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                        |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.UserSecret](schemas.md#codersdkusersecret) |

<h3 id="list-user-secrets-responseschema">Response Schema</h3>

Status Code **200**

| Name            | Type              | Required | Restrictions | Description                                                                                                                                                                                                                          |
|-----------------|-------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`  | array             | false    |              |                                                                                                                                                                                                                                      |
| `» created_at`  | string(date-time) | false    |              |                                                                                                                                                                                                                                      |
| `» description` | string            | false    |              |                                                                                                                                                                                                                                      |
| `» enabled`     | boolean           | false    |              | Enabled controls whether the secret is injected into workspaces. Disabled secrets remain visible and editable, but are not added to the agent manifest, so they are not exposed as environment variables or written to secret files. |
| `» env_name`    | string            | false    |              |                                                                                                                                                                                                                                      |
| `» file_path`   | string            | false    |              |                                                                                                                                                                                                                                      |
| `» id`          | string(uuid)      | false    |              |                                                                                                                                                                                                                                      |
| `» name`        | string            | false    |              |                                                                                                                                                                                                                                      |
| `» updated_at`  | string(date-time) | false    |              |                                                                                                                                                                                                                                      |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create a new user secret

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/{user}/secrets \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/{user}/secrets`

> Body parameter

```json
{
  "description": "string",
  "enabled": true,
  "env_name": "string",
  "file_path": "string",
  "name": "string",
  "value": "string"
}
```

### Parameters

| Name   | In   | Type                                                                           | Required | Description              |
|--------|------|--------------------------------------------------------------------------------|----------|--------------------------|
| `user` | path | string                                                                         | true     | User ID, username, or me |
| `body` | body | [codersdk.CreateUserSecretRequest](schemas.md#codersdkcreateusersecretrequest) | true     | Create secret request    |

### Example responses

> 201 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "description": "string",
  "enabled": true,
  "env_name": "string",
  "file_path": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                          | Description | Schema                                               |
|--------|------------------------------------------------------------------|-------------|------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)     | Created     | [codersdk.UserSecret](schemas.md#codersdkusersecret) |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1) | Bad Request | [codersdk.Response](schemas.md#codersdkresponse)     |
| 409    | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)    | Conflict    | [codersdk.Response](schemas.md#codersdkresponse)     |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Import user secrets from a file

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/{user}/secrets/batch \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/{user}/secrets/batch`

> Body parameter

```json
{
  "content": "string",
  "format": "env"
}
```

### Parameters

| Name   | In   | Type                                                                             | Required | Description              |
|--------|------|----------------------------------------------------------------------------------|----------|--------------------------|
| `user` | path | string                                                                           | true     | User ID, username, or me |
| `body` | body | [codersdk.ImportUserSecretsRequest](schemas.md#codersdkimportusersecretsrequest) | true     | Import secrets request   |

### Example responses

> 201 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "description": "string",
    "enabled": true,
    "env_name": "string",
    "file_path": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "updated_at": "2019-08-24T14:15:22Z"
  }
]
```

### Responses

| Status | Meaning                                                                 | Description                | Schema                                                        |
|--------|-------------------------------------------------------------------------|----------------------------|---------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)            | Created                    | array of [codersdk.UserSecret](schemas.md#codersdkusersecret) |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)        | Bad Request                | [codersdk.Response](schemas.md#codersdkresponse)              |
| 409    | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)           | Conflict                   | [codersdk.Response](schemas.md#codersdkresponse)              |
| 413    | [Payload Too Large](https://tools.ietf.org/html/rfc7231#section-6.5.11) | Request body exceeds 8 MiB | [codersdk.Response](schemas.md#codersdkresponse)              |

<h3 id="import-user-secrets-from-a-file-responseschema">Response Schema</h3>

Status Code **201**

| Name            | Type              | Required | Restrictions | Description                                                                                                                                                                                                                          |
|-----------------|-------------------|----------|--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`  | array             | false    |              |                                                                                                                                                                                                                                      |
| `» created_at`  | string(date-time) | false    |              |                                                                                                                                                                                                                                      |
| `» description` | string            | false    |              |                                                                                                                                                                                                                                      |
| `» enabled`     | boolean           | false    |              | Enabled controls whether the secret is injected into workspaces. Disabled secrets remain visible and editable, but are not added to the agent manifest, so they are not exposed as environment variables or written to secret files. |
| `» env_name`    | string            | false    |              |                                                                                                                                                                                                                                      |
| `» file_path`   | string            | false    |              |                                                                                                                                                                                                                                      |
| `» id`          | string(uuid)      | false    |              |                                                                                                                                                                                                                                      |
| `» name`        | string            | false    |              |                                                                                                                                                                                                                                      |
| `» updated_at`  | string(date-time) | false    |              |                                                                                                                                                                                                                                      |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get a user secret by name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/secrets/{name}`

### Parameters

| Name   | In   | Type   | Required | Description              |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true     | User ID, username, or me |
| `name` | path | string | true     | Secret name              |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "description": "string",
  "enabled": true,
  "env_name": "string",
  "file_path": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                               |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserSecret](schemas.md#codersdkusersecret) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete a user secret

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/users/{user}/secrets/{name}`

### Parameters

| Name   | In   | Type   | Required | Description              |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true     | User ID, username, or me |
| `name` | path | string | true     | Secret name              |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update a user secret

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/users/{user}/secrets/{name}`

> Body parameter

```json
{
  "description": "string",
  "enabled": true,
  "env_name": "string",
  "file_path": "string",
  "value": "string"
}
```

### Parameters

| Name   | In   | Type                                                                           | Required | Description              |
|--------|------|--------------------------------------------------------------------------------|----------|--------------------------|
| `user` | path | string                                                                         | true     | User ID, username, or me |
| `name` | path | string                                                                         | true     | Secret name              |
| `body` | body | [codersdk.UpdateUserSecretRequest](schemas.md#codersdkupdateusersecretrequest) | true     | Update secret request    |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "description": "string",
  "enabled": true,
  "env_name": "string",
  "file_path": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                          | Description | Schema                                               |
|--------|------------------------------------------------------------------|-------------|------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)          | OK          | [codersdk.UserSecret](schemas.md#codersdkusersecret) |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1) | Bad Request | [codersdk.Response](schemas.md#codersdkresponse)     |
| 409    | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)    | Conflict    | [codersdk.Response](schemas.md#codersdkresponse)     |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# TemplateBuilder

Source: https://coder.com/docs/reference/api/templatebuilder

<!-- DO NOT EDIT | GENERATED CONTENT -->

## List template builder base templates

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templatebuilder/bases \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templatebuilder/bases`

### Example responses

> 200 Response

```json
{
  "bases": [
    {
      "agents": [
        {
          "default": true,
          "display_name": "string",
          "name": "string"
        }
      ],
      "description": "string",
      "icon": "string",
      "id": "string",
      "name": "string",
      "os": "string",
      "prerequisites": "string",
      "variables": [
        {
          "default": [
            0
          ],
          "description": "string",
          "name": "string",
          "required": true,
          "sensitive": true,
          "type": "string"
        }
      ]
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.TemplateBuilderBasesResponse](schemas.md#codersdktemplatebuilderbasesresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Compose template from base and modules

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templatebuilder/compose \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templatebuilder/compose`

> Body parameter

```json
{
  "base_template_id": "string",
  "base_variable_values": {
    "property1": "string",
    "property2": "string"
  },
  "modules": [
    {
      "agent_name": "string",
      "id": "string",
      "variables": {
        "property1": "string",
        "property2": "string"
      }
    }
  ]
}
```

### Parameters

| Name   | In   | Type                                                                                       | Required | Description     |
|--------|------|--------------------------------------------------------------------------------------------|----------|-----------------|
| `body` | body | [codersdk.TemplateBuilderComposeRequest](schemas.md#codersdktemplatebuildercomposerequest) | true     | Compose request |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Compose and create a template

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templatebuilder/compose/template \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templatebuilder/compose/template`

> Body parameter

```json
{
  "base_template_id": "string",
  "base_variable_values": {
    "property1": "string",
    "property2": "string"
  },
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "modules": [
    {
      "agent_name": "string",
      "id": "string",
      "variables": {
        "property1": "string",
        "property2": "string"
      }
    }
  ],
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "provisioner_tags": {
    "property1": "string",
    "property2": "string"
  },
  "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82"
}
```

### Parameters

| Name   | In   | Type                                                                                                     | Required | Description             |
|--------|------|----------------------------------------------------------------------------------------------------------|----------|-------------------------|
| `body` | body | [codersdk.TemplateBuilderCreateTemplateRequest](schemas.md#codersdktemplatebuildercreatetemplaterequest) | true     | Create template request |

### Example responses

> 201 Response

```json
{
  "template": {
    "active_user_count": 0,
    "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
    "activity_bump_ms": 0,
    "agents_allowed": true,
    "allow_user_autostart": true,
    "allow_user_autostop": true,
    "allow_user_cancel_workspace_jobs": true,
    "allow_workspace_renames": true,
    "autostart_requirement": {
      "days_of_week": [
        "monday"
      ]
    },
    "autostop_requirement": {
      "days_of_week": [
        "monday"
      ],
      "weeks": 0
    },
    "build_time_stats": {
      "property1": {
        "p50": 123,
        "p95": 146
      },
      "property2": {
        "p50": 123,
        "p95": 146
      }
    },
    "cors_behavior": "simple",
    "created_at": "2019-08-24T14:15:22Z",
    "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
    "created_by_name": "string",
    "default_ttl_ms": 0,
    "deleted": true,
    "deprecated": true,
    "deprecation_message": "string",
    "description": "string",
    "disable_module_cache": true,
    "display_name": "string",
    "failure_ttl_ms": 0,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "max_port_share_level": "owner",
    "module_cache_disabled_by_deployment": true,
    "name": "string",
    "organization_display_name": "string",
    "organization_icon": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_name": "string",
    "provisioner": "terraform",
    "require_active_version": true,
    "time_til_autostop_notify_ms": 0,
    "time_til_dormant_autodelete_ms": 0,
    "time_til_dormant_ms": 0,
    "updated_at": "2019-08-24T14:15:22Z",
    "use_classic_parameter_flow": true
  }
}
```

### Responses

| Status | Meaning                                                               | Description     | Schema                                                                                                     |
|--------|-----------------------------------------------------------------------|-----------------|------------------------------------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2)          | Created         | [codersdk.TemplateBuilderCreateTemplateResponse](schemas.md#codersdktemplatebuildercreatetemplateresponse) |
| 400    | [Bad Request](https://tools.ietf.org/html/rfc7231#section-6.5.1)      | Bad Request     | [codersdk.Response](schemas.md#codersdkresponse)                                                           |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)        | Not Found       | [codersdk.Response](schemas.md#codersdkresponse)                                                           |
| 409    | [Conflict](https://tools.ietf.org/html/rfc7231#section-6.5.8)         | Conflict        | [codersdk.Response](schemas.md#codersdkresponse)                                                           |
| 504    | [Gateway Time-out](https://tools.ietf.org/html/rfc7231#section-6.6.5) | Gateway Timeout | [codersdk.Response](schemas.md#codersdkresponse)                                                           |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List template builder modules

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templatebuilder/modules \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templatebuilder/modules`

### Parameters

| Name   | In    | Type   | Required | Description                                             |
|--------|-------|--------|----------|---------------------------------------------------------|
| `base` | query | string | false    | Base template example ID for OS-compatibility filtering |

### Example responses

> 200 Response

```json
{
  "modules": [
    {
      "category": "string",
      "compatible_os": [
        "string"
      ],
      "conflicts_with": [
        "string"
      ],
      "description": "string",
      "display_name": "string",
      "icon": "string",
      "id": "string",
      "variables": [
        {
          "default": [
            0
          ],
          "description": "string",
          "name": "string",
          "required": true,
          "sensitive": true,
          "type": "string"
        }
      ],
      "version": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.TemplateBuilderModulesResponse](schemas.md#codersdktemplatebuildermodulesresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Report a template builder session event

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templatebuilder/sessions \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templatebuilder/sessions`

> Body parameter

```json
{
  "base_template_id": "string",
  "duration_seconds": 0,
  "event_type": "wizard_entry",
  "module_ids": [
    "string"
  ],
  "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  "success": true
}
```

### Parameters

| Name   | In   | Type                                                                                       | Required | Description   |
|--------|------|--------------------------------------------------------------------------------------------|----------|---------------|
| `body` | body | [codersdk.TemplateBuilderSessionRequest](schemas.md#codersdktemplatebuildersessionrequest) | true     | Session event |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Templates

Source: https://coder.com/docs/reference/api/templates

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get templates by organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templates \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/templates`

Returns a list of templates for the specified organization.
By default, only non-deprecated templates are returned.
To include deprecated templates, specify `deprecated:true` in the search query.

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  {
    "active_user_count": 0,
    "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
    "activity_bump_ms": 0,
    "agents_allowed": true,
    "allow_user_autostart": true,
    "allow_user_autostop": true,
    "allow_user_cancel_workspace_jobs": true,
    "allow_workspace_renames": true,
    "autostart_requirement": {
      "days_of_week": [
        "monday"
      ]
    },
    "autostop_requirement": {
      "days_of_week": [
        "monday"
      ],
      "weeks": 0
    },
    "build_time_stats": {
      "property1": {
        "p50": 123,
        "p95": 146
      },
      "property2": {
        "p50": 123,
        "p95": 146
      }
    },
    "cors_behavior": "simple",
    "created_at": "2019-08-24T14:15:22Z",
    "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
    "created_by_name": "string",
    "default_ttl_ms": 0,
    "deleted": true,
    "deprecated": true,
    "deprecation_message": "string",
    "description": "string",
    "disable_module_cache": true,
    "display_name": "string",
    "failure_ttl_ms": 0,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "max_port_share_level": "owner",
    "module_cache_disabled_by_deployment": true,
    "name": "string",
    "organization_display_name": "string",
    "organization_icon": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_name": "string",
    "provisioner": "terraform",
    "require_active_version": true,
    "time_til_autostop_notify_ms": 0,
    "time_til_dormant_autodelete_ms": 0,
    "time_til_dormant_ms": 0,
    "updated_at": "2019-08-24T14:15:22Z",
    "use_classic_parameter_flow": true
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                    |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Template](schemas.md#codersdktemplate) |

<h3 id="get-templates-by-organization-responseschema">Response Schema</h3>

Status Code **200**

| Name                                 | Type                                                                                     | Required | Restrictions | Description                                                                                                                                                                   |
|--------------------------------------|------------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                       | array                                                                                    | false    |              |                                                                                                                                                                               |
| `» active_user_count`                | integer                                                                                  | false    |              | Active user count is set to -1 when loading.                                                                                                                                  |
| `» active_version_id`                | string(uuid)                                                                             | false    |              |                                                                                                                                                                               |
| `» activity_bump_ms`                 | integer                                                                                  | false    |              |                                                                                                                                                                               |
| `» agents_allowed`                   | boolean                                                                                  | false    |              |                                                                                                                                                                               |
| `» allow_user_autostart`             | boolean                                                                                  | false    |              | Allow user autostart and AllowUserAutostop are enterprise-only. Their values are only used if your license is entitled to use the advanced template scheduling feature.       |
| `» allow_user_autostop`              | boolean                                                                                  | false    |              |                                                                                                                                                                               |
| `» allow_user_cancel_workspace_jobs` | boolean                                                                                  | false    |              |                                                                                                                                                                               |
| `» allow_workspace_renames`          | boolean                                                                                  | false    |              | Allow workspace renames permits users to rename workspaces built from this template. Renaming can be destructive for templates whose Terraform references the workspace name. |
| `» autostart_requirement`            | [codersdk.TemplateAutostartRequirement](schemas.md#codersdktemplateautostartrequirement) | false    |              |                                                                                                                                                                               |
| `»» days_of_week`                    | array                                                                                    | false    |              | Days of week is a list of days of the week in which autostart is allowed to happen. If no days are specified, autostart is not allowed.                                       |
| `» autostop_requirement`             | [codersdk.TemplateAutostopRequirement](schemas.md#codersdktemplateautostoprequirement)   | false    |              | Autostop requirement and AutostartRequirement are enterprise features. Its value is only used if your license is entitled to use the advanced template scheduling feature.    |
|`»» days_of_week`|array|false||Days of week is a list of days of the week on which restarts are required. Restarts happen within the user's quiet hours (in their configured timezone). If no days are specified, restarts are not required. Weekdays cannot be specified twice.
Restarts will only happen on weekdays in this list on weeks which line up with Weeks.|
|`»» weeks`|integer|false||Weeks is the number of weeks between required restarts. Weeks are synced across all workspaces (and Coder deployments) using modulo math on a hardcoded epoch week of January 2nd, 2023 (the first Monday of 2023). Values of 0 or 1 indicate weekly restarts. Values of 2 indicate fortnightly restarts, etc.|
|`» build_time_stats`|[codersdk.TemplateBuildTimeStats](schemas.md#codersdktemplatebuildtimestats)|false|||
|`»» [any property]`|[codersdk.TransitionStats](schemas.md#codersdktransitionstats)|false|||
|`»»» p50`|integer|false|||
|`»»» p95`|integer|false|||
|`» cors_behavior`|[codersdk.CORSBehavior](schemas.md#codersdkcorsbehavior)|false|||
|`» created_at`|string(date-time)|false|||
|`» created_by_id`|string(uuid)|false|||
|`» created_by_name`|string|false|||
|`» default_ttl_ms`|integer|false|||
|`» deleted`|boolean|false|||
|`» deprecated`|boolean|false|||
|`» deprecation_message`|string|false|||
|`» description`|string|false|||
|`» disable_module_cache`|boolean|false||Disable module cache disables the use of cached Terraform modules during provisioning for this template. It is read-only while ModuleCacheDisabledByDeployment is true.|
|`» display_name`|string|false|||
|`» failure_ttl_ms`|integer|false||Failure ttl ms TimeTilDormantMillis, and TimeTilDormantAutoDeleteMillis are enterprise-only. Their values are used if your license is entitled to use the advanced template scheduling feature.|
|`» icon`|string|false|||
|`» id`|string(uuid)|false|||
|`» max_port_share_level`|[codersdk.WorkspaceAgentPortShareLevel](schemas.md#codersdkworkspaceagentportsharelevel)|false|||
|`» module_cache_disabled_by_deployment`|boolean|false||Module cache disabled by deployment reports that the deployment disables the Terraform module cache for every template. Templates cannot opt back in, so the effective state is disabled regardless of DisableModuleCache.|
|`» name`|string|false|||
|`» organization_display_name`|string|false|||
|`» organization_icon`|string|false|||
|`» organization_id`|string(uuid)|false|||
|`» organization_name`|string(url)|false|||
|`» provisioner`|string|false|||
|`» require_active_version`|boolean|false||Require active version mandates that workspaces are built with the active template version.|
|`» time_til_autostop_notify_ms`|integer|false||Time til autostop notify ms is the duration before the workspace's autostop deadline at which a reminder notification is sent. 0 disables the notification.|
|`» time_til_dormant_autodelete_ms`|integer|false|||
|`» time_til_dormant_ms`|integer|false|||
|`» updated_at`|string(date-time)|false|||
|`» use_classic_parameter_flow`|boolean|false|||

#### Enumerated Values

| Property               | Value(s)                                           |
|------------------------|----------------------------------------------------|
| `cors_behavior`        | `passthru`, `simple`                               |
| `max_port_share_level` | `authenticated`, `organization`, `owner`, `public` |
| `provisioner`          | `terraform`                                        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create template by organization

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templates \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations/{organization}/templates`

> Body parameter

```json
{
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "cors_behavior": "simple",
  "default_ttl_ms": 0,
  "delete_ttl_ms": 0,
  "description": "string",
  "disable_everyone_group_access": true,
  "display_name": "string",
  "dormant_ttl_ms": 0,
  "failure_ttl_ms": 0,
  "icon": "string",
  "max_port_share_level": "owner",
  "name": "string",
  "require_active_version": true,
  "template_use_classic_parameter_flow": true,
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "time_til_autostop_notify_ms": 0
}
```

### Parameters

| Name           | In   | Type                                                                       | Required | Description     |
|----------------|------|----------------------------------------------------------------------------|----------|-----------------|
| `organization` | path | string                                                                     | true     | Organization ID |
| `body`         | body | [codersdk.CreateTemplateRequest](schemas.md#codersdkcreatetemplaterequest) | true     | Request body    |

### Example responses

> 200 Response

```json
{
  "active_user_count": 0,
  "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "build_time_stats": {
    "property1": {
      "p50": 123,
      "p95": 146
    },
    "property2": {
      "p50": 123,
      "p95": 146
    }
  },
  "cors_behavior": "simple",
  "created_at": "2019-08-24T14:15:22Z",
  "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
  "created_by_name": "string",
  "default_ttl_ms": 0,
  "deleted": true,
  "deprecated": true,
  "deprecation_message": "string",
  "description": "string",
  "disable_module_cache": true,
  "display_name": "string",
  "failure_ttl_ms": 0,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "max_port_share_level": "owner",
  "module_cache_disabled_by_deployment": true,
  "name": "string",
  "organization_display_name": "string",
  "organization_icon": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "provisioner": "terraform",
  "require_active_version": true,
  "time_til_autostop_notify_ms": 0,
  "time_til_dormant_autodelete_ms": 0,
  "time_til_dormant_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "use_classic_parameter_flow": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Template](schemas.md#codersdktemplate) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template examples by organization

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templates/examples \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/templates/examples`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |

### Example responses

> 200 Response

```json
[
  {
    "description": "string",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "markdown": "string",
    "name": "string",
    "tags": [
      "string"
    ],
    "url": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                  |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.TemplateExample](schemas.md#codersdktemplateexample) |

<h3 id="get-template-examples-by-organization-responseschema">Response Schema</h3>

Status Code **200**

| Name            | Type         | Required | Restrictions | Description |
|-----------------|--------------|----------|--------------|-------------|
| `[array item]`  | array        | false    |              |             |
| `» description` | string       | false    |              |             |
| `» icon`        | string       | false    |              |             |
| `» id`          | string(uuid) | false    |              |             |
| `» markdown`    | string       | false    |              |             |
| `» name`        | string       | false    |              |             |
| `» tags`        | array        | false    |              |             |
| `» url`         | string       | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get templates by organization and template name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templates/{templatename} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/templates/{templatename}`

### Parameters

| Name           | In   | Type         | Required | Description     |
|----------------|------|--------------|----------|-----------------|
| `organization` | path | string(uuid) | true     | Organization ID |
| `templatename` | path | string       | true     | Template name   |

### Example responses

> 200 Response

```json
{
  "active_user_count": 0,
  "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "build_time_stats": {
    "property1": {
      "p50": 123,
      "p95": 146
    },
    "property2": {
      "p50": 123,
      "p95": 146
    }
  },
  "cors_behavior": "simple",
  "created_at": "2019-08-24T14:15:22Z",
  "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
  "created_by_name": "string",
  "default_ttl_ms": 0,
  "deleted": true,
  "deprecated": true,
  "deprecation_message": "string",
  "description": "string",
  "disable_module_cache": true,
  "display_name": "string",
  "failure_ttl_ms": 0,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "max_port_share_level": "owner",
  "module_cache_disabled_by_deployment": true,
  "name": "string",
  "organization_display_name": "string",
  "organization_icon": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "provisioner": "terraform",
  "require_active_version": true,
  "time_til_autostop_notify_ms": 0,
  "time_til_dormant_autodelete_ms": 0,
  "time_til_dormant_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "use_classic_parameter_flow": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Template](schemas.md#codersdktemplate) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template version by organization, template, and name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templates/{templatename}/versions/{templateversionname} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/templates/{templatename}/versions/{templateversionname}`

### Parameters

| Name                  | In   | Type         | Required | Description           |
|-----------------------|------|--------------|----------|-----------------------|
| `organization`        | path | string(uuid) | true     | Organization ID       |
| `templatename`        | path | string       | true     | Template name         |
| `templateversionname` | path | string       | true     | Template version name |

### Example responses

> 200 Response

```json
{
  "archived": true,
  "created_at": "2019-08-24T14:15:22Z",
  "created_by": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "message": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "readme": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "UNSUPPORTED_WORKSPACES"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                         |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.TemplateVersion](schemas.md#codersdktemplateversion) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get previous template version by organization, template, and name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templates/{templatename}/versions/{templateversionname}/previous \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/templates/{templatename}/versions/{templateversionname}/previous`

### Parameters

| Name                  | In   | Type         | Required | Description           |
|-----------------------|------|--------------|----------|-----------------------|
| `organization`        | path | string(uuid) | true     | Organization ID       |
| `templatename`        | path | string       | true     | Template name         |
| `templateversionname` | path | string       | true     | Template version name |

### Example responses

> 200 Response

```json
{
  "archived": true,
  "created_at": "2019-08-24T14:15:22Z",
  "created_by": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "message": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "readme": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "UNSUPPORTED_WORKSPACES"
  ]
}
```

### Responses

| Status | Meaning                                                         | Description | Schema                                                         |
|--------|-----------------------------------------------------------------|-------------|----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)         | OK          | [codersdk.TemplateVersion](schemas.md#codersdktemplateversion) |
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |                                                                |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create template version by organization

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templateversions \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations/{organization}/templateversions`

> Body parameter

```json
{
  "example_id": "string",
  "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  "message": "string",
  "name": "string",
  "provisioner": "terraform",
  "storage_method": "file",
  "tags": {
    "property1": "string",
    "property2": "string"
  },
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "user_variable_values": [
    {
      "name": "string",
      "value": "string"
    }
  ]
}
```

### Parameters

| Name           | In   | Type                                                                                     | Required | Description                     |
|----------------|------|------------------------------------------------------------------------------------------|----------|---------------------------------|
| `organization` | path | string(uuid)                                                                             | true     | Organization ID                 |
| `body`         | body | [codersdk.CreateTemplateVersionRequest](schemas.md#codersdkcreatetemplateversionrequest) | true     | Create template version request |

### Example responses

> 201 Response

```json
{
  "archived": true,
  "created_at": "2019-08-24T14:15:22Z",
  "created_by": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "message": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "readme": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "UNSUPPORTED_WORKSPACES"
  ]
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                         |
|--------|--------------------------------------------------------------|-------------|----------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.TemplateVersion](schemas.md#codersdktemplateversion) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get all templates

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templates \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templates`

Returns a list of templates.
By default, only non-deprecated templates are returned.
To include deprecated templates, specify `deprecated:true` in the search query.

### Example responses

> 200 Response

```json
[
  {
    "active_user_count": 0,
    "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
    "activity_bump_ms": 0,
    "agents_allowed": true,
    "allow_user_autostart": true,
    "allow_user_autostop": true,
    "allow_user_cancel_workspace_jobs": true,
    "allow_workspace_renames": true,
    "autostart_requirement": {
      "days_of_week": [
        "monday"
      ]
    },
    "autostop_requirement": {
      "days_of_week": [
        "monday"
      ],
      "weeks": 0
    },
    "build_time_stats": {
      "property1": {
        "p50": 123,
        "p95": 146
      },
      "property2": {
        "p50": 123,
        "p95": 146
      }
    },
    "cors_behavior": "simple",
    "created_at": "2019-08-24T14:15:22Z",
    "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
    "created_by_name": "string",
    "default_ttl_ms": 0,
    "deleted": true,
    "deprecated": true,
    "deprecation_message": "string",
    "description": "string",
    "disable_module_cache": true,
    "display_name": "string",
    "failure_ttl_ms": 0,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "max_port_share_level": "owner",
    "module_cache_disabled_by_deployment": true,
    "name": "string",
    "organization_display_name": "string",
    "organization_icon": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "organization_name": "string",
    "provisioner": "terraform",
    "require_active_version": true,
    "time_til_autostop_notify_ms": 0,
    "time_til_dormant_autodelete_ms": 0,
    "time_til_dormant_ms": 0,
    "updated_at": "2019-08-24T14:15:22Z",
    "use_classic_parameter_flow": true
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                    |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Template](schemas.md#codersdktemplate) |

<h3 id="get-all-templates-responseschema">Response Schema</h3>

Status Code **200**

| Name                                 | Type                                                                                     | Required | Restrictions | Description                                                                                                                                                                   |
|--------------------------------------|------------------------------------------------------------------------------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                       | array                                                                                    | false    |              |                                                                                                                                                                               |
| `» active_user_count`                | integer                                                                                  | false    |              | Active user count is set to -1 when loading.                                                                                                                                  |
| `» active_version_id`                | string(uuid)                                                                             | false    |              |                                                                                                                                                                               |
| `» activity_bump_ms`                 | integer                                                                                  | false    |              |                                                                                                                                                                               |
| `» agents_allowed`                   | boolean                                                                                  | false    |              |                                                                                                                                                                               |
| `» allow_user_autostart`             | boolean                                                                                  | false    |              | Allow user autostart and AllowUserAutostop are enterprise-only. Their values are only used if your license is entitled to use the advanced template scheduling feature.       |
| `» allow_user_autostop`              | boolean                                                                                  | false    |              |                                                                                                                                                                               |
| `» allow_user_cancel_workspace_jobs` | boolean                                                                                  | false    |              |                                                                                                                                                                               |
| `» allow_workspace_renames`          | boolean                                                                                  | false    |              | Allow workspace renames permits users to rename workspaces built from this template. Renaming can be destructive for templates whose Terraform references the workspace name. |
| `» autostart_requirement`            | [codersdk.TemplateAutostartRequirement](schemas.md#codersdktemplateautostartrequirement) | false    |              |                                                                                                                                                                               |
| `»» days_of_week`                    | array                                                                                    | false    |              | Days of week is a list of days of the week in which autostart is allowed to happen. If no days are specified, autostart is not allowed.                                       |
| `» autostop_requirement`             | [codersdk.TemplateAutostopRequirement](schemas.md#codersdktemplateautostoprequirement)   | false    |              | Autostop requirement and AutostartRequirement are enterprise features. Its value is only used if your license is entitled to use the advanced template scheduling feature.    |
|`»» days_of_week`|array|false||Days of week is a list of days of the week on which restarts are required. Restarts happen within the user's quiet hours (in their configured timezone). If no days are specified, restarts are not required. Weekdays cannot be specified twice.
Restarts will only happen on weekdays in this list on weeks which line up with Weeks.|
|`»» weeks`|integer|false||Weeks is the number of weeks between required restarts. Weeks are synced across all workspaces (and Coder deployments) using modulo math on a hardcoded epoch week of January 2nd, 2023 (the first Monday of 2023). Values of 0 or 1 indicate weekly restarts. Values of 2 indicate fortnightly restarts, etc.|
|`» build_time_stats`|[codersdk.TemplateBuildTimeStats](schemas.md#codersdktemplatebuildtimestats)|false|||
|`»» [any property]`|[codersdk.TransitionStats](schemas.md#codersdktransitionstats)|false|||
|`»»» p50`|integer|false|||
|`»»» p95`|integer|false|||
|`» cors_behavior`|[codersdk.CORSBehavior](schemas.md#codersdkcorsbehavior)|false|||
|`» created_at`|string(date-time)|false|||
|`» created_by_id`|string(uuid)|false|||
|`» created_by_name`|string|false|||
|`» default_ttl_ms`|integer|false|||
|`» deleted`|boolean|false|||
|`» deprecated`|boolean|false|||
|`» deprecation_message`|string|false|||
|`» description`|string|false|||
|`» disable_module_cache`|boolean|false||Disable module cache disables the use of cached Terraform modules during provisioning for this template. It is read-only while ModuleCacheDisabledByDeployment is true.|
|`» display_name`|string|false|||
|`» failure_ttl_ms`|integer|false||Failure ttl ms TimeTilDormantMillis, and TimeTilDormantAutoDeleteMillis are enterprise-only. Their values are used if your license is entitled to use the advanced template scheduling feature.|
|`» icon`|string|false|||
|`» id`|string(uuid)|false|||
|`» max_port_share_level`|[codersdk.WorkspaceAgentPortShareLevel](schemas.md#codersdkworkspaceagentportsharelevel)|false|||
|`» module_cache_disabled_by_deployment`|boolean|false||Module cache disabled by deployment reports that the deployment disables the Terraform module cache for every template. Templates cannot opt back in, so the effective state is disabled regardless of DisableModuleCache.|
|`» name`|string|false|||
|`» organization_display_name`|string|false|||
|`» organization_icon`|string|false|||
|`» organization_id`|string(uuid)|false|||
|`» organization_name`|string(url)|false|||
|`» provisioner`|string|false|||
|`» require_active_version`|boolean|false||Require active version mandates that workspaces are built with the active template version.|
|`» time_til_autostop_notify_ms`|integer|false||Time til autostop notify ms is the duration before the workspace's autostop deadline at which a reminder notification is sent. 0 disables the notification.|
|`» time_til_dormant_autodelete_ms`|integer|false|||
|`» time_til_dormant_ms`|integer|false|||
|`» updated_at`|string(date-time)|false|||
|`» use_classic_parameter_flow`|boolean|false|||

#### Enumerated Values

| Property               | Value(s)                                           |
|------------------------|----------------------------------------------------|
| `cors_behavior`        | `passthru`, `simple`                               |
| `max_port_share_level` | `authenticated`, `organization`, `owner`, `public` |
| `provisioner`          | `terraform`                                        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template examples

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templates/examples \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templates/examples`

### Example responses

> 200 Response

```json
[
  {
    "description": "string",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "markdown": "string",
    "name": "string",
    "tags": [
      "string"
    ],
    "url": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                  |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.TemplateExample](schemas.md#codersdktemplateexample) |

<h3 id="get-template-examples-responseschema">Response Schema</h3>

Status Code **200**

| Name            | Type         | Required | Restrictions | Description |
|-----------------|--------------|----------|--------------|-------------|
| `[array item]`  | array        | false    |              |             |
| `» description` | string       | false    |              |             |
| `» icon`        | string       | false    |              |             |
| `» id`          | string(uuid) | false    |              |             |
| `» markdown`    | string       | false    |              |             |
| `» name`        | string       | false    |              |             |
| `» tags`        | array        | false    |              |             |
| `» url`         | string       | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template settings by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templates/{template} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templates/{template}`

### Parameters

| Name       | In   | Type         | Required | Description |
|------------|------|--------------|----------|-------------|
| `template` | path | string(uuid) | true     | Template ID |

### Example responses

> 200 Response

```json
{
  "active_user_count": 0,
  "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "build_time_stats": {
    "property1": {
      "p50": 123,
      "p95": 146
    },
    "property2": {
      "p50": 123,
      "p95": 146
    }
  },
  "cors_behavior": "simple",
  "created_at": "2019-08-24T14:15:22Z",
  "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
  "created_by_name": "string",
  "default_ttl_ms": 0,
  "deleted": true,
  "deprecated": true,
  "deprecation_message": "string",
  "description": "string",
  "disable_module_cache": true,
  "display_name": "string",
  "failure_ttl_ms": 0,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "max_port_share_level": "owner",
  "module_cache_disabled_by_deployment": true,
  "name": "string",
  "organization_display_name": "string",
  "organization_icon": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "provisioner": "terraform",
  "require_active_version": true,
  "time_til_autostop_notify_ms": 0,
  "time_til_dormant_autodelete_ms": 0,
  "time_til_dormant_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "use_classic_parameter_flow": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Template](schemas.md#codersdktemplate) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete template by ID

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/templates/{template} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/templates/{template}`

### Parameters

| Name       | In   | Type         | Required | Description |
|------------|------|--------------|----------|-------------|
| `template` | path | string(uuid) | true     | Template ID |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update template settings by ID

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/templates/{template} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/templates/{template}`

> Body parameter

```json
{
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "cors_behavior": "simple",
  "default_ttl_ms": 0,
  "deprecation_message": "string",
  "description": "string",
  "disable_everyone_group_access": true,
  "disable_module_cache": true,
  "display_name": "string",
  "failure_ttl_ms": 0,
  "icon": "string",
  "max_port_share_level": "owner",
  "name": "string",
  "require_active_version": true,
  "time_til_autostop_notify_ms": 0,
  "time_til_dormant_autodelete_ms": 0,
  "time_til_dormant_ms": 0,
  "update_workspace_dormant_at": true,
  "update_workspace_last_used_at": true,
  "use_classic_parameter_flow": true
}
```

### Parameters

| Name       | In   | Type                                                                 | Required | Description                     |
|------------|------|----------------------------------------------------------------------|----------|---------------------------------|
| `template` | path | string(uuid)                                                         | true     | Template ID                     |
| `body`     | body | [codersdk.UpdateTemplateMeta](schemas.md#codersdkupdatetemplatemeta) | true     | Patch template settings request |

### Example responses

> 200 Response

```json
{
  "active_user_count": 0,
  "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc",
  "activity_bump_ms": 0,
  "agents_allowed": true,
  "allow_user_autostart": true,
  "allow_user_autostop": true,
  "allow_user_cancel_workspace_jobs": true,
  "allow_workspace_renames": true,
  "autostart_requirement": {
    "days_of_week": [
      "monday"
    ]
  },
  "autostop_requirement": {
    "days_of_week": [
      "monday"
    ],
    "weeks": 0
  },
  "build_time_stats": {
    "property1": {
      "p50": 123,
      "p95": 146
    },
    "property2": {
      "p50": 123,
      "p95": 146
    }
  },
  "cors_behavior": "simple",
  "created_at": "2019-08-24T14:15:22Z",
  "created_by_id": "9377d689-01fb-4abf-8450-3368d2c1924f",
  "created_by_name": "string",
  "default_ttl_ms": 0,
  "deleted": true,
  "deprecated": true,
  "deprecation_message": "string",
  "description": "string",
  "disable_module_cache": true,
  "display_name": "string",
  "failure_ttl_ms": 0,
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "max_port_share_level": "owner",
  "module_cache_disabled_by_deployment": true,
  "name": "string",
  "organization_display_name": "string",
  "organization_icon": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "provisioner": "terraform",
  "require_active_version": true,
  "time_til_autostop_notify_ms": 0,
  "time_til_dormant_autodelete_ms": 0,
  "time_til_dormant_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z",
  "use_classic_parameter_flow": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Template](schemas.md#codersdktemplate) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template DAUs by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templates/{template}/daus \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templates/{template}/daus`

### Parameters

| Name       | In   | Type         | Required | Description |
|------------|------|--------------|----------|-------------|
| `template` | path | string(uuid) | true     | Template ID |

### Example responses

> 200 Response

```json
{
  "entries": [
    {
      "amount": 0,
      "date": "string"
    }
  ],
  "tz_hour_offset": 0
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.DAUsResponse](schemas.md#codersdkdausresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List template versions by template ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templates/{template}/versions`

### Parameters

| Name               | In    | Type         | Required | Description                           |
|--------------------|-------|--------------|----------|---------------------------------------|
| `template`         | path  | string(uuid) | true     | Template ID                           |
| `after_id`         | query | string(uuid) | false    | After ID                              |
| `include_archived` | query | boolean      | false    | Include archived versions in the list |
| `limit`            | query | integer      | false    | Page limit                            |
| `offset`           | query | integer      | false    | Page offset                           |

### Example responses

> 200 Response

```json
[
  {
    "archived": true,
    "created_at": "2019-08-24T14:15:22Z",
    "created_by": {
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "username": "string"
    },
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "message": "string",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "readme": "string",
    "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
    "updated_at": "2019-08-24T14:15:22Z",
    "warnings": [
      "UNSUPPORTED_WORKSPACES"
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                  |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.TemplateVersion](schemas.md#codersdktemplateversion) |

<h3 id="list-template-versions-by-template-id-responseschema">Response Schema</h3>

Status Code **200**

| Name                             | Type                                                                         | Required | Restrictions | Description                                                                                                                                                         |
|----------------------------------|------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                   | array                                                                        | false    |              |                                                                                                                                                                     |
| `» archived`                     | boolean                                                                      | false    |              |                                                                                                                                                                     |
| `» created_at`                   | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `» created_by`                   | [codersdk.MinimalUser](schemas.md#codersdkminimaluser)                       | false    |              |                                                                                                                                                                     |
| `»» avatar_url`                  | string(uri)                                                                  | false    |              |                                                                                                                                                                     |
| `»» id`                          | string(uuid)                                                                 | true     |              |                                                                                                                                                                     |
| `»» name`                        | string                                                                       | false    |              |                                                                                                                                                                     |
| `»» username`                    | string                                                                       | true     |              |                                                                                                                                                                     |
| `» has_external_agent`           | boolean                                                                      | false    |              |                                                                                                                                                                     |
| `» id`                           | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `» job`                          | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob)                 | false    |              |                                                                                                                                                                     |
| `»» available_workers`           | array                                                                        | false    |              |                                                                                                                                                                     |
| `»» canceled_at`                 | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `»» completed_at`                | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `»» created_at`                  | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `»» error`                       | string                                                                       | false    |              |                                                                                                                                                                     |
| `»» error_code`                  | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode)                     | false    |              |                                                                                                                                                                     |
| `»» file_id`                     | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» id`                          | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» initiator_id`                | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» input`                       | [codersdk.ProvisionerJobInput](schemas.md#codersdkprovisionerjobinput)       | false    |              |                                                                                                                                                                     |
| `»»» error`                      | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» template_version_id`        | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»»» workspace_build_id`         | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» logs_overflowed`             | boolean                                                                      | false    |              |                                                                                                                                                                     |
| `»» metadata`                    | [codersdk.ProvisionerJobMetadata](schemas.md#codersdkprovisionerjobmetadata) | false    |              |                                                                                                                                                                     |
| `»»» template_display_name`      | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» template_icon`              | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» template_id`                | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»»» template_name`              | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» template_version_name`      | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» workspace_build_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)       | false    |              |                                                                                                                                                                     |
| `»»» workspace_id`               | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»»» workspace_name`             | string                                                                       | false    |              |                                                                                                                                                                     |
| `»» organization_id`             | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» queue_position`              | integer                                                                      | false    |              |                                                                                                                                                                     |
| `»» queue_size`                  | integer                                                                      | false    |              |                                                                                                                                                                     |
| `»» started_at`                  | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `»» status`                      | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus)     | false    |              |                                                                                                                                                                     |
| `»» tags`                        | object                                                                       | false    |              |                                                                                                                                                                     |
| `»»» [any property]`             | string                                                                       | false    |              |                                                                                                                                                                     |
| `»» type`                        | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype)         | false    |              |                                                                                                                                                                     |
| `»» worker_id`                   | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» worker_name`                 | string                                                                       | false    |              |                                                                                                                                                                     |
| `» matched_provisioners`         | [codersdk.MatchedProvisioners](schemas.md#codersdkmatchedprovisioners)       | false    |              |                                                                                                                                                                     |
| `»» available`                   | integer                                                                      | false    |              | Available is the number of provisioner daemons that are available to take jobs. This may be less than the count if some provisioners are busy or have been stopped. |
| `»» count`                       | integer                                                                      | false    |              | Count is the number of provisioner daemons that matched the given tags. If the count is 0, it means no provisioner daemons matched the requested tags.              |
| `»» most_recently_seen`          | string(date-time)                                                            | false    |              | Most recently seen is the most recently seen time of the set of matched provisioners. If no provisioners matched, this field will be null.                          |
| `» message`                      | string                                                                       | false    |              |                                                                                                                                                                     |
| `» name`                         | string                                                                       | false    |              |                                                                                                                                                                     |
| `» organization_id`              | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `» readme`                       | string                                                                       | false    |              |                                                                                                                                                                     |
| `» template_id`                  | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `» updated_at`                   | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `» warnings`                     | array                                                                        | false    |              |                                                                                                                                                                     |

#### Enumerated Values

| Property                     | Value(s)                                                                 |
|------------------------------|--------------------------------------------------------------------------|
| `error_code`                 | `INSUFFICIENT_QUOTA`, `REQUIRED_TEMPLATE_VARIABLES`                      |
| `workspace_build_transition` | `delete`, `start`, `stop`                                                |
| `status`                     | `canceled`, `canceling`, `failed`, `pending`, `running`, `succeeded`     |
| `type`                       | `template_version_dry_run`, `template_version_import`, `workspace_build` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update active template version by template ID

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/templates/{template}/versions \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/templates/{template}/versions`

> Body parameter

```json
{
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08"
}
```

### Parameters

| Name       | In   | Type                                                                                   | Required | Description               |
|------------|------|----------------------------------------------------------------------------------------|----------|---------------------------|
| `template` | path | string(uuid)                                                                           | true     | Template ID               |
| `body`     | body | [codersdk.UpdateActiveTemplateVersion](schemas.md#codersdkupdateactivetemplateversion) | true     | Modified template version |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Archive template unused versions by template id

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templates/{template}/versions/archive \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templates/{template}/versions/archive`

> Body parameter

```json
{
  "all": true
}
```

### Parameters

| Name       | In   | Type                                                                                         | Required | Description     |
|------------|------|----------------------------------------------------------------------------------------------|----------|-----------------|
| `template` | path | string(uuid)                                                                                 | true     | Template ID     |
| `body`     | body | [codersdk.ArchiveTemplateVersionsRequest](schemas.md#codersdkarchivetemplateversionsrequest) | true     | Archive request |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template version by template ID and name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templateversionname} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templates/{template}/versions/{templateversionname}`

### Parameters

| Name                  | In   | Type         | Required | Description           |
|-----------------------|------|--------------|----------|-----------------------|
| `template`            | path | string(uuid) | true     | Template ID           |
| `templateversionname` | path | string       | true     | Template version name |

### Example responses

> 200 Response

```json
[
  {
    "archived": true,
    "created_at": "2019-08-24T14:15:22Z",
    "created_by": {
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "username": "string"
    },
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "message": "string",
    "name": "string",
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "readme": "string",
    "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
    "updated_at": "2019-08-24T14:15:22Z",
    "warnings": [
      "UNSUPPORTED_WORKSPACES"
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                  |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.TemplateVersion](schemas.md#codersdktemplateversion) |

<h3 id="get-template-version-by-template-id-and-name-responseschema">Response Schema</h3>

Status Code **200**

| Name                             | Type                                                                         | Required | Restrictions | Description                                                                                                                                                         |
|----------------------------------|------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                   | array                                                                        | false    |              |                                                                                                                                                                     |
| `» archived`                     | boolean                                                                      | false    |              |                                                                                                                                                                     |
| `» created_at`                   | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `» created_by`                   | [codersdk.MinimalUser](schemas.md#codersdkminimaluser)                       | false    |              |                                                                                                                                                                     |
| `»» avatar_url`                  | string(uri)                                                                  | false    |              |                                                                                                                                                                     |
| `»» id`                          | string(uuid)                                                                 | true     |              |                                                                                                                                                                     |
| `»» name`                        | string                                                                       | false    |              |                                                                                                                                                                     |
| `»» username`                    | string                                                                       | true     |              |                                                                                                                                                                     |
| `» has_external_agent`           | boolean                                                                      | false    |              |                                                                                                                                                                     |
| `» id`                           | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `» job`                          | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob)                 | false    |              |                                                                                                                                                                     |
| `»» available_workers`           | array                                                                        | false    |              |                                                                                                                                                                     |
| `»» canceled_at`                 | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `»» completed_at`                | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `»» created_at`                  | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `»» error`                       | string                                                                       | false    |              |                                                                                                                                                                     |
| `»» error_code`                  | [codersdk.JobErrorCode](schemas.md#codersdkjoberrorcode)                     | false    |              |                                                                                                                                                                     |
| `»» file_id`                     | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» id`                          | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» initiator_id`                | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» input`                       | [codersdk.ProvisionerJobInput](schemas.md#codersdkprovisionerjobinput)       | false    |              |                                                                                                                                                                     |
| `»»» error`                      | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» template_version_id`        | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»»» workspace_build_id`         | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» logs_overflowed`             | boolean                                                                      | false    |              |                                                                                                                                                                     |
| `»» metadata`                    | [codersdk.ProvisionerJobMetadata](schemas.md#codersdkprovisionerjobmetadata) | false    |              |                                                                                                                                                                     |
| `»»» template_display_name`      | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» template_icon`              | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» template_id`                | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»»» template_name`              | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» template_version_name`      | string                                                                       | false    |              |                                                                                                                                                                     |
| `»»» workspace_build_transition` | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)       | false    |              |                                                                                                                                                                     |
| `»»» workspace_id`               | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»»» workspace_name`             | string                                                                       | false    |              |                                                                                                                                                                     |
| `»» organization_id`             | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» queue_position`              | integer                                                                      | false    |              |                                                                                                                                                                     |
| `»» queue_size`                  | integer                                                                      | false    |              |                                                                                                                                                                     |
| `»» started_at`                  | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `»» status`                      | [codersdk.ProvisionerJobStatus](schemas.md#codersdkprovisionerjobstatus)     | false    |              |                                                                                                                                                                     |
| `»» tags`                        | object                                                                       | false    |              |                                                                                                                                                                     |
| `»»» [any property]`             | string                                                                       | false    |              |                                                                                                                                                                     |
| `»» type`                        | [codersdk.ProvisionerJobType](schemas.md#codersdkprovisionerjobtype)         | false    |              |                                                                                                                                                                     |
| `»» worker_id`                   | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `»» worker_name`                 | string                                                                       | false    |              |                                                                                                                                                                     |
| `» matched_provisioners`         | [codersdk.MatchedProvisioners](schemas.md#codersdkmatchedprovisioners)       | false    |              |                                                                                                                                                                     |
| `»» available`                   | integer                                                                      | false    |              | Available is the number of provisioner daemons that are available to take jobs. This may be less than the count if some provisioners are busy or have been stopped. |
| `»» count`                       | integer                                                                      | false    |              | Count is the number of provisioner daemons that matched the given tags. If the count is 0, it means no provisioner daemons matched the requested tags.              |
| `»» most_recently_seen`          | string(date-time)                                                            | false    |              | Most recently seen is the most recently seen time of the set of matched provisioners. If no provisioners matched, this field will be null.                          |
| `» message`                      | string                                                                       | false    |              |                                                                                                                                                                     |
| `» name`                         | string                                                                       | false    |              |                                                                                                                                                                     |
| `» organization_id`              | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `» readme`                       | string                                                                       | false    |              |                                                                                                                                                                     |
| `» template_id`                  | string(uuid)                                                                 | false    |              |                                                                                                                                                                     |
| `» updated_at`                   | string(date-time)                                                            | false    |              |                                                                                                                                                                     |
| `» warnings`                     | array                                                                        | false    |              |                                                                                                                                                                     |

#### Enumerated Values

| Property                     | Value(s)                                                                 |
|------------------------------|--------------------------------------------------------------------------|
| `error_code`                 | `INSUFFICIENT_QUOTA`, `REQUIRED_TEMPLATE_VARIABLES`                      |
| `workspace_build_transition` | `delete`, `start`, `stop`                                                |
| `status`                     | `canceled`, `canceling`, `failed`, `pending`, `running`, `succeeded`     |
| `type`                       | `template_version_dry_run`, `template_version_import`, `workspace_build` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template version by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
{
  "archived": true,
  "created_at": "2019-08-24T14:15:22Z",
  "created_by": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "message": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "readme": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "UNSUPPORTED_WORKSPACES"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                         |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.TemplateVersion](schemas.md#codersdktemplateversion) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Patch template version by ID

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion} \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/templateversions/{templateversion}`

> Body parameter

```json
{
  "message": "string",
  "name": "string"
}
```

### Parameters

| Name              | In   | Type                                                                                   | Required | Description                    |
|-------------------|------|----------------------------------------------------------------------------------------|----------|--------------------------------|
| `templateversion` | path | string(uuid)                                                                           | true     | Template version ID            |
| `body`            | body | [codersdk.PatchTemplateVersionRequest](schemas.md#codersdkpatchtemplateversionrequest) | true     | Patch template version request |

### Example responses

> 200 Response

```json
{
  "archived": true,
  "created_at": "2019-08-24T14:15:22Z",
  "created_by": {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  },
  "has_external_agent": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "job": {
    "available_workers": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "canceled_at": "2019-08-24T14:15:22Z",
    "completed_at": "2019-08-24T14:15:22Z",
    "created_at": "2019-08-24T14:15:22Z",
    "error": "string",
    "error_code": "REQUIRED_TEMPLATE_VARIABLES",
    "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "input": {
      "error": "string",
      "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
      "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
    },
    "logs_overflowed": true,
    "metadata": {
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_version_name": "string",
      "workspace_build_transition": "start",
      "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
      "workspace_name": "string"
    },
    "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
    "queue_position": 0,
    "queue_size": 0,
    "started_at": "2019-08-24T14:15:22Z",
    "status": "pending",
    "tags": {
      "property1": "string",
      "property2": "string"
    },
    "type": "template_version_import",
    "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
    "worker_name": "string"
  },
  "matched_provisioners": {
    "available": 0,
    "count": 0,
    "most_recently_seen": "2019-08-24T14:15:22Z"
  },
  "message": "string",
  "name": "string",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "readme": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "updated_at": "2019-08-24T14:15:22Z",
  "warnings": [
    "UNSUPPORTED_WORKSPACES"
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                         |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.TemplateVersion](schemas.md#codersdktemplateversion) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Archive template version

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/archive \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templateversions/{templateversion}/archive`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Cancel template version by ID

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion}/cancel \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/templateversions/{templateversion}/cancel`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create template version dry-run

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/dry-run \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templateversions/{templateversion}/dry-run`

> Body parameter

```json
{
  "rich_parameter_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "user_variable_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "workspace_name": "string"
}
```

### Parameters

| Name              | In   | Type                                                                                                 | Required | Description         |
|-------------------|------|------------------------------------------------------------------------------------------------------|----------|---------------------|
| `templateversion` | path | string(uuid)                                                                                         | true     | Template version ID |
| `body`            | body | [codersdk.CreateTemplateVersionDryRunRequest](schemas.md#codersdkcreatetemplateversiondryrunrequest) | true     | Dry-run request     |

### Example responses

> 201 Response

```json
{
  "available_workers": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "canceled_at": "2019-08-24T14:15:22Z",
  "completed_at": "2019-08-24T14:15:22Z",
  "created_at": "2019-08-24T14:15:22Z",
  "error": "string",
  "error_code": "REQUIRED_TEMPLATE_VARIABLES",
  "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "input": {
    "error": "string",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
  },
  "logs_overflowed": true,
  "metadata": {
    "template_display_name": "string",
    "template_icon": "string",
    "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
    "template_name": "string",
    "template_version_name": "string",
    "workspace_build_transition": "start",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string"
  },
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "queue_position": 0,
  "queue_size": 0,
  "started_at": "2019-08-24T14:15:22Z",
  "status": "pending",
  "tags": {
    "property1": "string",
    "property2": "string"
  },
  "type": "template_version_import",
  "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
  "worker_name": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                       |
|--------|--------------------------------------------------------------|-------------|--------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template version dry-run by job ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/dry-run/{jobID} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/dry-run/{jobID}`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |
| `jobID`           | path | string(uuid) | true     | Job ID              |

### Example responses

> 200 Response

```json
{
  "available_workers": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "canceled_at": "2019-08-24T14:15:22Z",
  "completed_at": "2019-08-24T14:15:22Z",
  "created_at": "2019-08-24T14:15:22Z",
  "error": "string",
  "error_code": "REQUIRED_TEMPLATE_VARIABLES",
  "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
  "input": {
    "error": "string",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
  },
  "logs_overflowed": true,
  "metadata": {
    "template_display_name": "string",
    "template_icon": "string",
    "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
    "template_name": "string",
    "template_version_name": "string",
    "workspace_build_transition": "start",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string"
  },
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "queue_position": 0,
  "queue_size": 0,
  "started_at": "2019-08-24T14:15:22Z",
  "status": "pending",
  "tags": {
    "property1": "string",
    "property2": "string"
  },
  "type": "template_version_import",
  "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
  "worker_name": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                       |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ProvisionerJob](schemas.md#codersdkprovisionerjob) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Cancel template version dry-run by job ID

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion}/dry-run/{jobID}/cancel \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/templateversions/{templateversion}/dry-run/{jobID}/cancel`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `jobID`           | path | string(uuid) | true     | Job ID              |
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template version dry-run logs by job ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/dry-run/{jobID}/logs \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/dry-run/{jobID}/logs`

### Parameters

| Name              | In    | Type         | Required | Description                                                                                                                                 |
|-------------------|-------|--------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `templateversion` | path  | string(uuid) | true     | Template version ID                                                                                                                         |
| `jobID`           | path  | string(uuid) | true     | Job ID                                                                                                                                      |
| `before`          | query | integer      | false    | Before Unix timestamp                                                                                                                       |
| `after`           | query | integer      | false    | After Unix timestamp                                                                                                                        |
| `follow`          | query | boolean      | false    | Follow log stream                                                                                                                           |
| `format`          | query | string       | false    | Log output format. Accepted: 'json' (default), 'text' (plain text with RFC3339 timestamps and ANSI colors). Not supported with follow=true. |

#### Enumerated Values

| Parameter | Value(s)       |
|-----------|----------------|
| `format`  | `json`, `text` |

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "id": 0,
    "log_level": "trace",
    "log_source": "provisioner_daemon",
    "output": "string",
    "stage": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ProvisionerJobLog](schemas.md#codersdkprovisionerjoblog) |

<h3 id="get-template-version-dry-run-logs-by-job-id-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type                                               | Required | Restrictions | Description |
|----------------|----------------------------------------------------|----------|--------------|-------------|
| `[array item]` | array                                              | false    |              |             |
| `» created_at` | string(date-time)                                  | false    |              |             |
| `» id`         | integer                                            | false    |              |             |
| `» log_level`  | [codersdk.LogLevel](schemas.md#codersdkloglevel)   | false    |              |             |
| `» log_source` | [codersdk.LogSource](schemas.md#codersdklogsource) | false    |              |             |
| `» output`     | string                                             | false    |              |             |
| `» stage`      | string                                             | false    |              |             |

#### Enumerated Values

| Property     | Value(s)                                  |
|--------------|-------------------------------------------|
| `log_level`  | `debug`, `error`, `info`, `trace`, `warn` |
| `log_source` | `provisioner`, `provisioner_daemon`       |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template version dry-run matched provisioners

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/dry-run/{jobID}/matched-provisioners \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/dry-run/{jobID}/matched-provisioners`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |
| `jobID`           | path | string(uuid) | true     | Job ID              |

### Example responses

> 200 Response

```json
{
  "available": 0,
  "count": 0,
  "most_recently_seen": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                 |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.MatchedProvisioners](schemas.md#codersdkmatchedprovisioners) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template version dry-run resources by job ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/dry-run/{jobID}/resources \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/dry-run/{jobID}/resources`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |
| `jobID`           | path | string(uuid) | true     | Job ID              |

### Example responses

> 200 Response

```json
[
  {
    "agents": [
      {
        "api_version": "string",
        "apps": [
          {
            "command": "string",
            "display_name": "string",
            "external": true,
            "group": "string",
            "health": "disabled",
            "healthcheck": {
              "interval": 0,
              "threshold": 0,
              "url": "string"
            },
            "hidden": true,
            "icon": "string",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "open_in": "slim-window",
            "sharing_level": "owner",
            "slug": "string",
            "statuses": [
              {
                "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                "created_at": "2019-08-24T14:15:22Z",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "message": "string",
                "needs_user_attention": true,
                "state": "working",
                "uri": "string",
                "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
              }
            ],
            "subdomain": true,
            "subdomain_name": "string",
            "tooltip": "string",
            "url": "string"
          }
        ],
        "architecture": "string",
        "connection_timeout_seconds": 0,
        "created_at": "2019-08-24T14:15:22Z",
        "directory": "string",
        "disconnected_at": "2019-08-24T14:15:22Z",
        "display_apps": [
          "vscode"
        ],
        "environment_variables": {
          "property1": "string",
          "property2": "string"
        },
        "expanded_directory": "string",
        "first_connected_at": "2019-08-24T14:15:22Z",
        "health": {
          "healthy": false,
          "reason": "agent has lost connection"
        },
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "instance_id": "string",
        "last_connected_at": "2019-08-24T14:15:22Z",
        "latency": {
          "property1": {
            "latency_ms": 0,
            "preferred": true
          },
          "property2": {
            "latency_ms": 0,
            "preferred": true
          }
        },
        "lifecycle_state": "created",
        "log_sources": [
          {
            "created_at": "2019-08-24T14:15:22Z",
            "display_name": "string",
            "icon": "string",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
          }
        ],
        "logs_length": 0,
        "logs_overflowed": true,
        "metadata": [
          {
            "description": {
              "display_name": "string",
              "interval": 0,
              "key": "string",
              "script": "string",
              "timeout": 0
            },
            "result": {
              "age": 0,
              "collected_at": "2019-08-24T14:15:22Z",
              "error": "string",
              "value": "string"
            }
          }
        ],
        "name": "string",
        "operating_system": "string",
        "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
        "ready_at": "2019-08-24T14:15:22Z",
        "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
        "scripts": [
          {
            "cron": "string",
            "display_name": "string",
            "exit_code": 0,
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "log_path": "string",
            "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
            "run_on_start": true,
            "run_on_stop": true,
            "script": "string",
            "start_blocks_login": true,
            "status": "ok",
            "timeout": 0
          }
        ],
        "started_at": "2019-08-24T14:15:22Z",
        "startup_script_behavior": "blocking",
        "status": "connecting",
        "subsystems": [
          "envbox"
        ],
        "troubleshooting_url": "string",
        "updated_at": "2019-08-24T14:15:22Z",
        "version": "string"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "hide": true,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
    "metadata": [
      {
        "key": "string",
        "sensitive": true,
        "value": "string"
      }
    ],
    "name": "string",
    "type": "string",
    "workspace_transition": "start"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.WorkspaceResource](schemas.md#codersdkworkspaceresource) |

<h3 id="get-template-version-dry-run-resources-by-job-id-responseschema">Response Schema</h3>

Status Code **200**

| Name                            | Type                                                                                                   | Required | Restrictions | Description                                                                                                                                                                                                                                                            |
|---------------------------------|--------------------------------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                  | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `» agents`                      | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» api_version`                | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» apps`                       | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» command`                   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              | Display name is a friendly name for the app.                                                                                                                                                                                                                           |
| `»»» external`                  | boolean                                                                                                | false    |              | External specifies whether the URL should be opened externally on the client or not.                                                                                                                                                                                   |
| `»»» group`                     | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» health`                    | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» healthcheck`               | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck)                                                 | false    |              | Healthcheck specifies the configuration for checking app health.                                                                                                                                                                                                       |
| `»»»» interval`                 | integer                                                                                                | false    |              | Interval specifies the seconds between each health check.                                                                                                                                                                                                              |
| `»»»» threshold`                | integer                                                                                                | false    |              | Threshold specifies the number of consecutive failed health checks before returning "unhealthy".                                                                                                                                                                       |
| `»»»» url`                      | string                                                                                                 | false    |              | URL specifies the endpoint to check for the app health.                                                                                                                                                                                                                |
| `»»» hidden`                    | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» icon`                      | string                                                                                                 | false    |              | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard.                                                                                                                                                                       |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» open_in`                   | [codersdk.WorkspaceAppOpenIn](schemas.md#codersdkworkspaceappopenin)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» sharing_level`             | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel)                       | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» slug`                      | string                                                                                                 | false    |              | Slug is a unique identifier within the agent.                                                                                                                                                                                                                          |
| `»»» statuses`                  | array                                                                                                  | false    |              | Statuses is a list of statuses for the app.                                                                                                                                                                                                                            |
| `»»»» agent_id`                 | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» app_id`                   | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» created_at`               | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» icon`                     | string                                                                                                 | false    |              | Deprecated: This field is unused and will be removed in a future version. Icon is an external URL to an icon that will be rendered in the UI.                                                                                                                          |
| `»»»» id`                       | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» message`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» needs_user_attention`     | boolean                                                                                                | false    |              | Deprecated: This field is unused and will be removed in a future version. NeedsUserAttention specifies whether the status needs user attention.                                                                                                                        |
| `»»»» state`                    | [codersdk.WorkspaceAppStatusState](schemas.md#codersdkworkspaceappstatusstate)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» uri`                      | string                                                                                                 | false    |              | Uri is the URI of the resource that the status is for. e.g. https://github.com/org/repo/pull/123 e.g. file:///path/to/file                                                                                                                                             |
| `»»»» workspace_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» subdomain`                 | boolean                                                                                                | false    |              | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI.                         |
| `»»» subdomain_name`            | string                                                                                                 | false    |              | Subdomain name is the application domain exposed on the `coder server`.                                                                                                                                                                                                |
| `»»» tooltip`                   | string                                                                                                 | false    |              | Tooltip is an optional markdown supported field that is displayed when hovering over workspace apps in the UI.                                                                                                                                                         |
| `»»» url`                       | string                                                                                                 | false    |              | URL is the address being proxied to inside the workspace. If external is specified, this will be opened on the client.                                                                                                                                                 |
| `»» architecture`               | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» connection_timeout_seconds` | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» created_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» directory`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» disconnected_at`            | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» display_apps`               | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» environment_variables`      | object                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» [any property]`            | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» expanded_directory`         | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» first_connected_at`         | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» health`                     | [codersdk.WorkspaceAgentHealth](schemas.md#codersdkworkspaceagenthealth)                               | false    |              | Health reports the health of the agent.                                                                                                                                                                                                                                |
| `»»» healthy`                   | boolean                                                                                                | false    |              | Healthy is true if the agent is healthy.                                                                                                                                                                                                                               |
| `»»» reason`                    | string                                                                                                 | false    |              | Reason is a human-readable explanation of the agent's health. It is empty if Healthy is true.                                                                                                                                                                          |
| `»» id`                         | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» instance_id`                | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» last_connected_at`          | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» latency`                    | object                                                                                                 | false    |              | Latency is mapped by region name (e.g. "New York City", "Seattle").                                                                                                                                                                                                    |
| `»»» [any property]`            | [codersdk.DERPRegion](schemas.md#codersdkderpregion)                                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» latency_ms`               | number                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» preferred`                | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» lifecycle_state`            | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `»» log_sources`                | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» created_at`                | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» icon`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» workspace_agent_id`        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» logs_length`                | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» logs_overflowed`            | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» metadata`                   | array                                                                                                  | false    |              | Metadata is only populated on the workspaces list endpoint when the request opts in with the include_agent_metadata search key, and it only carries the requested keys. The description's script is always empty here: it can be long, and list consumers want values. |
| `»»» description`               | [codersdk.WorkspaceAgentMetadataDescription](schemas.md#codersdkworkspaceagentmetadatadescription)     | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» display_name`             | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» interval`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» key`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» script`                   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» timeout`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» result`                    | [codersdk.WorkspaceAgentMetadataResult](schemas.md#codersdkworkspaceagentmetadataresult)               | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» age`                      | integer                                                                                                | false    |              | Age is the number of seconds since the metadata was collected. It is provided in addition to CollectedAt to protect against clock skew.                                                                                                                                |
| `»»»» collected_at`             | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» error`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» value`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» name`                       | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» operating_system`           | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» parent_id`                  | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» ready_at`                   | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» resource_id`                | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» scripts`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» cron`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» exit_code`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» log_path`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» log_source_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» run_on_start`              | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» run_on_stop`               | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» script`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» start_blocks_login`        | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» status`                    | [codersdk.WorkspaceAgentScriptStatus](schemas.md#codersdkworkspaceagentscriptstatus)                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» timeout`                   | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» started_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» startup_script_behavior`    | [codersdk.WorkspaceAgentStartupScriptBehavior](schemas.md#codersdkworkspaceagentstartupscriptbehavior) | false    |              | Startup script behavior is a legacy field that is deprecated in favor of the `coder_script` resource. It's only referenced by old clients. Deprecated: Remove in the future!                                                                                           |
| `»» status`                     | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus)                               | false    |              |                                                                                                                                                                                                                                                                        |
| `»» subsystems`                 | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» troubleshooting_url`        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» updated_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» version`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» created_at`                  | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `» daily_cost`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» hide`                        | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» icon`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» id`                          | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» job_id`                      | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» metadata`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» key`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» sensitive`                  | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» value`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» name`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» type`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» workspace_transition`        | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)                                 | false    |              |                                                                                                                                                                                                                                                                        |

#### Enumerated Values

| Property                  | Value(s)                                                                                                                     |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------|
| `health`                  | `disabled`, `healthy`, `initializing`, `unhealthy`                                                                           |
| `open_in`                 | `slim-window`, `tab`                                                                                                         |
| `sharing_level`           | `authenticated`, `organization`, `owner`, `public`                                                                           |
| `state`                   | `complete`, `failure`, `idle`, `working`                                                                                     |
| `lifecycle_state`         | `created`, `off`, `ready`, `shutdown_error`, `shutdown_timeout`, `shutting_down`, `start_error`, `start_timeout`, `starting` |
| `status`                  | `connected`, `connecting`, `disconnected`, `exit_failure`, `ok`, `pipes_left_open`, `timed_out`, `timeout`                   |
| `startup_script_behavior` | `blocking`, `non-blocking`                                                                                                   |
| `workspace_transition`    | `delete`, `start`, `stop`                                                                                                    |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Open dynamic parameters WebSocket by template version

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/dynamic-parameters \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/dynamic-parameters`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Responses

| Status | Meaning                                                                  | Description         | Schema |
|--------|--------------------------------------------------------------------------|---------------------|--------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Evaluate dynamic parameters for template version

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/dynamic-parameters/evaluate \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templateversions/{templateversion}/dynamic-parameters/evaluate`

> Body parameter

```json
{
  "id": 0,
  "inputs": {
    "property1": "string",
    "property2": "string"
  },
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05"
}
```

### Parameters

| Name              | In   | Type                                                                             | Required | Description              |
|-------------------|------|----------------------------------------------------------------------------------|----------|--------------------------|
| `templateversion` | path | string(uuid)                                                                     | true     | Template version ID      |
| `body`            | body | [codersdk.DynamicParametersRequest](schemas.md#codersdkdynamicparametersrequest) | true     | Initial parameter values |

### Example responses

> 200 Response

```json
{
  "diagnostics": [
    {
      "detail": "string",
      "extra": {
        "code": "string"
      },
      "severity": "error",
      "summary": "string"
    }
  ],
  "id": 0,
  "parameters": [
    {
      "default_value": {
        "valid": true,
        "value": "string"
      },
      "description": "string",
      "diagnostics": [
        {
          "detail": "string",
          "extra": {
            "code": "string"
          },
          "severity": "error",
          "summary": "string"
        }
      ],
      "display_name": "string",
      "ephemeral": true,
      "form_type": "",
      "icon": "string",
      "mutable": true,
      "name": "string",
      "options": [
        {
          "description": "string",
          "icon": "string",
          "name": "string",
          "value": {
            "valid": true,
            "value": "string"
          }
        }
      ],
      "order": 0,
      "required": true,
      "styling": {
        "disabled": true,
        "label": "string",
        "mask_input": true,
        "placeholder": "string"
      },
      "type": "string",
      "validations": [
        {
          "validation_error": "string",
          "validation_max": 0,
          "validation_min": 0,
          "validation_monotonic": "string",
          "validation_regex": "string"
        }
      ],
      "value": {
        "valid": true,
        "value": "string"
      }
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                             |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.DynamicParametersResponse](schemas.md#codersdkdynamicparametersresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get external auth by template version

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/external-auth \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/external-auth`

### Parameters

| Name              | In    | Type         | Required | Description                                                               |
|-------------------|-------|--------------|----------|---------------------------------------------------------------------------|
| `templateversion` | path  | string(uuid) | true     | Template version ID                                                       |
| `user_id`         | query | string(uuid) | false    | Owner to report external auth state for. Defaults to the requesting user. |

### Example responses

> 200 Response

```json
[
  {
    "authenticate_url": "string",
    "authenticated": true,
    "display_icon": "string",
    "display_name": "string",
    "id": "string",
    "optional": true,
    "type": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                          |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.TemplateVersionExternalAuth](schemas.md#codersdktemplateversionexternalauth) |

<h3 id="get-external-auth-by-template-version-responseschema">Response Schema</h3>

Status Code **200**

| Name                 | Type    | Required | Restrictions | Description |
|----------------------|---------|----------|--------------|-------------|
| `[array item]`       | array   | false    |              |             |
| `» authenticate_url` | string  | false    |              |             |
| `» authenticated`    | boolean | false    |              |             |
| `» display_icon`     | string  | false    |              |             |
| `» display_name`     | string  | false    |              |             |
| `» id`               | string  | false    |              |             |
| `» optional`         | boolean | false    |              |             |
| `» type`             | string  | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get logs by template version

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/logs \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/logs`

### Parameters

| Name              | In    | Type         | Required | Description                                                                                                                                 |
|-------------------|-------|--------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------|
| `templateversion` | path  | string(uuid) | true     | Template version ID                                                                                                                         |
| `before`          | query | integer      | false    | Before log id                                                                                                                               |
| `after`           | query | integer      | false    | After log id                                                                                                                                |
| `follow`          | query | boolean      | false    | Follow log stream                                                                                                                           |
| `format`          | query | string       | false    | Log output format. Accepted: 'json' (default), 'text' (plain text with RFC3339 timestamps and ANSI colors). Not supported with follow=true. |

#### Enumerated Values

| Parameter | Value(s)       |
|-----------|----------------|
| `format`  | `json`, `text` |

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "id": 0,
    "log_level": "trace",
    "log_source": "provisioner_daemon",
    "output": "string",
    "stage": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.ProvisionerJobLog](schemas.md#codersdkprovisionerjoblog) |

<h3 id="get-logs-by-template-version-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type                                               | Required | Restrictions | Description |
|----------------|----------------------------------------------------|----------|--------------|-------------|
| `[array item]` | array                                              | false    |              |             |
| `» created_at` | string(date-time)                                  | false    |              |             |
| `» id`         | integer                                            | false    |              |             |
| `» log_level`  | [codersdk.LogLevel](schemas.md#codersdkloglevel)   | false    |              |             |
| `» log_source` | [codersdk.LogSource](schemas.md#codersdklogsource) | false    |              |             |
| `» output`     | string                                             | false    |              |             |
| `» stage`      | string                                             | false    |              |             |

#### Enumerated Values

| Property     | Value(s)                                  |
|--------------|-------------------------------------------|
| `log_level`  | `debug`, `error`, `info`, `trace`, `warn` |
| `log_source` | `provisioner`, `provisioner_daemon`       |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Removed: Get parameters by template version

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/parameters \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/parameters`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template version presets

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/presets \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/presets`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
[
  {
    "default": true,
    "description": "string",
    "desiredPrebuildInstances": 0,
    "icon": "string",
    "id": "string",
    "name": "string",
    "parameters": [
      {
        "name": "string",
        "value": "string"
      }
    ]
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Preset](schemas.md#codersdkpreset) |

<h3 id="get-template-version-presets-responseschema">Response Schema</h3>

Status Code **200**

| Name                         | Type    | Required | Restrictions | Description |
|------------------------------|---------|----------|--------------|-------------|
| `[array item]`               | array   | false    |              |             |
| `» default`                  | boolean | false    |              |             |
| `» description`              | string  | false    |              |             |
| `» desiredPrebuildInstances` | integer | false    |              |             |
| `» icon`                     | string  | false    |              |             |
| `» id`                       | string  | false    |              |             |
| `» name`                     | string  | false    |              |             |
| `» parameters`               | array   | false    |              |             |
| `»» name`                    | string  | false    |              |             |
| `»» value`                   | string  | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get resources by template version

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/resources \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/resources`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
[
  {
    "agents": [
      {
        "api_version": "string",
        "apps": [
          {
            "command": "string",
            "display_name": "string",
            "external": true,
            "group": "string",
            "health": "disabled",
            "healthcheck": {
              "interval": 0,
              "threshold": 0,
              "url": "string"
            },
            "hidden": true,
            "icon": "string",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "open_in": "slim-window",
            "sharing_level": "owner",
            "slug": "string",
            "statuses": [
              {
                "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                "created_at": "2019-08-24T14:15:22Z",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "message": "string",
                "needs_user_attention": true,
                "state": "working",
                "uri": "string",
                "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
              }
            ],
            "subdomain": true,
            "subdomain_name": "string",
            "tooltip": "string",
            "url": "string"
          }
        ],
        "architecture": "string",
        "connection_timeout_seconds": 0,
        "created_at": "2019-08-24T14:15:22Z",
        "directory": "string",
        "disconnected_at": "2019-08-24T14:15:22Z",
        "display_apps": [
          "vscode"
        ],
        "environment_variables": {
          "property1": "string",
          "property2": "string"
        },
        "expanded_directory": "string",
        "first_connected_at": "2019-08-24T14:15:22Z",
        "health": {
          "healthy": false,
          "reason": "agent has lost connection"
        },
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "instance_id": "string",
        "last_connected_at": "2019-08-24T14:15:22Z",
        "latency": {
          "property1": {
            "latency_ms": 0,
            "preferred": true
          },
          "property2": {
            "latency_ms": 0,
            "preferred": true
          }
        },
        "lifecycle_state": "created",
        "log_sources": [
          {
            "created_at": "2019-08-24T14:15:22Z",
            "display_name": "string",
            "icon": "string",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
          }
        ],
        "logs_length": 0,
        "logs_overflowed": true,
        "metadata": [
          {
            "description": {
              "display_name": "string",
              "interval": 0,
              "key": "string",
              "script": "string",
              "timeout": 0
            },
            "result": {
              "age": 0,
              "collected_at": "2019-08-24T14:15:22Z",
              "error": "string",
              "value": "string"
            }
          }
        ],
        "name": "string",
        "operating_system": "string",
        "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
        "ready_at": "2019-08-24T14:15:22Z",
        "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
        "scripts": [
          {
            "cron": "string",
            "display_name": "string",
            "exit_code": 0,
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "log_path": "string",
            "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
            "run_on_start": true,
            "run_on_stop": true,
            "script": "string",
            "start_blocks_login": true,
            "status": "ok",
            "timeout": 0
          }
        ],
        "started_at": "2019-08-24T14:15:22Z",
        "startup_script_behavior": "blocking",
        "status": "connecting",
        "subsystems": [
          "envbox"
        ],
        "troubleshooting_url": "string",
        "updated_at": "2019-08-24T14:15:22Z",
        "version": "string"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "hide": true,
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
    "metadata": [
      {
        "key": "string",
        "sensitive": true,
        "value": "string"
      }
    ],
    "name": "string",
    "type": "string",
    "workspace_transition": "start"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                      |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.WorkspaceResource](schemas.md#codersdkworkspaceresource) |

<h3 id="get-resources-by-template-version-responseschema">Response Schema</h3>

Status Code **200**

| Name                            | Type                                                                                                   | Required | Restrictions | Description                                                                                                                                                                                                                                                            |
|---------------------------------|--------------------------------------------------------------------------------------------------------|----------|--------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`                  | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `» agents`                      | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» api_version`                | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» apps`                       | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» command`                   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              | Display name is a friendly name for the app.                                                                                                                                                                                                                           |
| `»»» external`                  | boolean                                                                                                | false    |              | External specifies whether the URL should be opened externally on the client or not.                                                                                                                                                                                   |
| `»»» group`                     | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» health`                    | [codersdk.WorkspaceAppHealth](schemas.md#codersdkworkspaceapphealth)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» healthcheck`               | [codersdk.Healthcheck](schemas.md#codersdkhealthcheck)                                                 | false    |              | Healthcheck specifies the configuration for checking app health.                                                                                                                                                                                                       |
| `»»»» interval`                 | integer                                                                                                | false    |              | Interval specifies the seconds between each health check.                                                                                                                                                                                                              |
| `»»»» threshold`                | integer                                                                                                | false    |              | Threshold specifies the number of consecutive failed health checks before returning "unhealthy".                                                                                                                                                                       |
| `»»»» url`                      | string                                                                                                 | false    |              | URL specifies the endpoint to check for the app health.                                                                                                                                                                                                                |
| `»»» hidden`                    | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» icon`                      | string                                                                                                 | false    |              | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard.                                                                                                                                                                       |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» open_in`                   | [codersdk.WorkspaceAppOpenIn](schemas.md#codersdkworkspaceappopenin)                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» sharing_level`             | [codersdk.WorkspaceAppSharingLevel](schemas.md#codersdkworkspaceappsharinglevel)                       | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» slug`                      | string                                                                                                 | false    |              | Slug is a unique identifier within the agent.                                                                                                                                                                                                                          |
| `»»» statuses`                  | array                                                                                                  | false    |              | Statuses is a list of statuses for the app.                                                                                                                                                                                                                            |
| `»»»» agent_id`                 | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» app_id`                   | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» created_at`               | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» icon`                     | string                                                                                                 | false    |              | Deprecated: This field is unused and will be removed in a future version. Icon is an external URL to an icon that will be rendered in the UI.                                                                                                                          |
| `»»»» id`                       | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» message`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» needs_user_attention`     | boolean                                                                                                | false    |              | Deprecated: This field is unused and will be removed in a future version. NeedsUserAttention specifies whether the status needs user attention.                                                                                                                        |
| `»»»» state`                    | [codersdk.WorkspaceAppStatusState](schemas.md#codersdkworkspaceappstatusstate)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» uri`                      | string                                                                                                 | false    |              | Uri is the URI of the resource that the status is for. e.g. https://github.com/org/repo/pull/123 e.g. file:///path/to/file                                                                                                                                             |
| `»»»» workspace_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» subdomain`                 | boolean                                                                                                | false    |              | Subdomain denotes whether the app should be accessed via a path on the `coder server` or via a hostname-based dev URL. If this is set to true and there is no app wildcard configured on the server, the app will not be accessible in the UI.                         |
| `»»» subdomain_name`            | string                                                                                                 | false    |              | Subdomain name is the application domain exposed on the `coder server`.                                                                                                                                                                                                |
| `»»» tooltip`                   | string                                                                                                 | false    |              | Tooltip is an optional markdown supported field that is displayed when hovering over workspace apps in the UI.                                                                                                                                                         |
| `»»» url`                       | string                                                                                                 | false    |              | URL is the address being proxied to inside the workspace. If external is specified, this will be opened on the client.                                                                                                                                                 |
| `»» architecture`               | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» connection_timeout_seconds` | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» created_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» directory`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» disconnected_at`            | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» display_apps`               | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» environment_variables`      | object                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» [any property]`            | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» expanded_directory`         | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» first_connected_at`         | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» health`                     | [codersdk.WorkspaceAgentHealth](schemas.md#codersdkworkspaceagenthealth)                               | false    |              | Health reports the health of the agent.                                                                                                                                                                                                                                |
| `»»» healthy`                   | boolean                                                                                                | false    |              | Healthy is true if the agent is healthy.                                                                                                                                                                                                                               |
| `»»» reason`                    | string                                                                                                 | false    |              | Reason is a human-readable explanation of the agent's health. It is empty if Healthy is true.                                                                                                                                                                          |
| `»» id`                         | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» instance_id`                | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» last_connected_at`          | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» latency`                    | object                                                                                                 | false    |              | Latency is mapped by region name (e.g. "New York City", "Seattle").                                                                                                                                                                                                    |
| `»»» [any property]`            | [codersdk.DERPRegion](schemas.md#codersdkderpregion)                                                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» latency_ms`               | number                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» preferred`                | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» lifecycle_state`            | [codersdk.WorkspaceAgentLifecycle](schemas.md#codersdkworkspaceagentlifecycle)                         | false    |              |                                                                                                                                                                                                                                                                        |
| `»» log_sources`                | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» created_at`                | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» icon`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» workspace_agent_id`        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» logs_length`                | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» logs_overflowed`            | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» metadata`                   | array                                                                                                  | false    |              | Metadata is only populated on the workspaces list endpoint when the request opts in with the include_agent_metadata search key, and it only carries the requested keys. The description's script is always empty here: it can be long, and list consumers want values. |
| `»»» description`               | [codersdk.WorkspaceAgentMetadataDescription](schemas.md#codersdkworkspaceagentmetadatadescription)     | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» display_name`             | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» interval`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» key`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» script`                   | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» timeout`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» result`                    | [codersdk.WorkspaceAgentMetadataResult](schemas.md#codersdkworkspaceagentmetadataresult)               | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» age`                      | integer                                                                                                | false    |              | Age is the number of seconds since the metadata was collected. It is provided in addition to CollectedAt to protect against clock skew.                                                                                                                                |
| `»»»» collected_at`             | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» error`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»»» value`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» name`                       | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» operating_system`           | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» parent_id`                  | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» ready_at`                   | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» resource_id`                | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»» scripts`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» cron`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» display_name`              | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» exit_code`                 | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» id`                        | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» log_path`                  | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» log_source_id`             | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» run_on_start`              | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» run_on_stop`               | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» script`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» start_blocks_login`        | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» status`                    | [codersdk.WorkspaceAgentScriptStatus](schemas.md#codersdkworkspaceagentscriptstatus)                   | false    |              |                                                                                                                                                                                                                                                                        |
| `»»» timeout`                   | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» started_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» startup_script_behavior`    | [codersdk.WorkspaceAgentStartupScriptBehavior](schemas.md#codersdkworkspaceagentstartupscriptbehavior) | false    |              | Startup script behavior is a legacy field that is deprecated in favor of the `coder_script` resource. It's only referenced by old clients. Deprecated: Remove in the future!                                                                                           |
| `»» status`                     | [codersdk.WorkspaceAgentStatus](schemas.md#codersdkworkspaceagentstatus)                               | false    |              |                                                                                                                                                                                                                                                                        |
| `»» subsystems`                 | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» troubleshooting_url`        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» updated_at`                 | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `»» version`                    | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» created_at`                  | string(date-time)                                                                                      | false    |              |                                                                                                                                                                                                                                                                        |
| `» daily_cost`                  | integer                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» hide`                        | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `» icon`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» id`                          | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» job_id`                      | string(uuid)                                                                                           | false    |              |                                                                                                                                                                                                                                                                        |
| `» metadata`                    | array                                                                                                  | false    |              |                                                                                                                                                                                                                                                                        |
| `»» key`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `»» sensitive`                  | boolean                                                                                                | false    |              |                                                                                                                                                                                                                                                                        |
| `»» value`                      | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» name`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» type`                        | string                                                                                                 | false    |              |                                                                                                                                                                                                                                                                        |
| `» workspace_transition`        | [codersdk.WorkspaceTransition](schemas.md#codersdkworkspacetransition)                                 | false    |              |                                                                                                                                                                                                                                                                        |

#### Enumerated Values

| Property                  | Value(s)                                                                                                                     |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------|
| `health`                  | `disabled`, `healthy`, `initializing`, `unhealthy`                                                                           |
| `open_in`                 | `slim-window`, `tab`                                                                                                         |
| `sharing_level`           | `authenticated`, `organization`, `owner`, `public`                                                                           |
| `state`                   | `complete`, `failure`, `idle`, `working`                                                                                     |
| `lifecycle_state`         | `created`, `off`, `ready`, `shutdown_error`, `shutdown_timeout`, `shutting_down`, `start_error`, `start_timeout`, `starting` |
| `status`                  | `connected`, `connecting`, `disconnected`, `exit_failure`, `ok`, `pipes_left_open`, `timed_out`, `timeout`                   |
| `startup_script_behavior` | `blocking`, `non-blocking`                                                                                                   |
| `workspace_transition`    | `delete`, `start`, `stop`                                                                                                    |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get rich parameters by template version

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/rich-parameters \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/rich-parameters`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
[
  {
    "default_value": "string",
    "description": "string",
    "description_plaintext": "string",
    "display_name": "string",
    "ephemeral": true,
    "form_type": "",
    "icon": "string",
    "mutable": true,
    "name": "string",
    "options": [
      {
        "description": "string",
        "icon": "string",
        "name": "string",
        "value": "string"
      }
    ],
    "required": true,
    "type": "string",
    "validation_error": "string",
    "validation_max": 0,
    "validation_min": 0,
    "validation_monotonic": "increasing",
    "validation_regex": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                    |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.TemplateVersionParameter](schemas.md#codersdktemplateversionparameter) |

<h3 id="get-rich-parameters-by-template-version-responseschema">Response Schema</h3>

Status Code **200**

| Name                      | Type                                                                             | Required | Restrictions | Description                                                                                        |
|---------------------------|----------------------------------------------------------------------------------|----------|--------------|----------------------------------------------------------------------------------------------------|
| `[array item]`            | array                                                                            | false    |              |                                                                                                    |
| `» default_value`         | string                                                                           | false    |              |                                                                                                    |
| `» description`           | string                                                                           | false    |              |                                                                                                    |
| `» description_plaintext` | string                                                                           | false    |              |                                                                                                    |
| `» display_name`          | string                                                                           | false    |              |                                                                                                    |
| `» ephemeral`             | boolean                                                                          | false    |              |                                                                                                    |
| `» form_type`             | string                                                                           | false    |              | Form type has an enum value of empty string, `""`. Keep the leading comma in the enums struct tag. |
| `» icon`                  | string                                                                           | false    |              |                                                                                                    |
| `» mutable`               | boolean                                                                          | false    |              |                                                                                                    |
| `» name`                  | string                                                                           | false    |              |                                                                                                    |
| `» options`               | array                                                                            | false    |              |                                                                                                    |
| `»» description`          | string                                                                           | false    |              |                                                                                                    |
| `»» icon`                 | string                                                                           | false    |              |                                                                                                    |
| `»» name`                 | string                                                                           | false    |              |                                                                                                    |
| `»» value`                | string                                                                           | false    |              |                                                                                                    |
| `» required`              | boolean                                                                          | false    |              |                                                                                                    |
| `» type`                  | string                                                                           | false    |              |                                                                                                    |
| `» validation_error`      | string                                                                           | false    |              |                                                                                                    |
| `» validation_max`        | integer                                                                          | false    |              |                                                                                                    |
| `» validation_min`        | integer                                                                          | false    |              |                                                                                                    |
| `» validation_monotonic`  | [codersdk.ValidationMonotonicOrder](schemas.md#codersdkvalidationmonotonicorder) | false    |              |                                                                                                    |
| `» validation_regex`      | string                                                                           | false    |              |                                                                                                    |

#### Enumerated Values

| Property               | Value(s)                                                                                                            |
|------------------------|---------------------------------------------------------------------------------------------------------------------|
| `form_type`            | ``, `checkbox`, `dropdown`, `error`, `input`, `multi-select`, `radio`, `slider`, `switch`, `tag-select`, `textarea` |
| `type`                 | `bool`, `list(string)`, `number`, `string`                                                                          |
| `validation_monotonic` | `decreasing`, `increasing`                                                                                          |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Removed: Get schema by template version

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/schema \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/schema`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Unarchive template version

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/unarchive \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/templateversions/{templateversion}/unarchive`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get template variables by template version

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/variables \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/templateversions/{templateversion}/variables`

### Parameters

| Name              | In   | Type         | Required | Description         |
|-------------------|------|--------------|----------|---------------------|
| `templateversion` | path | string(uuid) | true     | Template version ID |

### Example responses

> 200 Response

```json
[
  {
    "default_value": "string",
    "description": "string",
    "name": "string",
    "required": true,
    "sensitive": true,
    "type": "string",
    "value": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                  |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.TemplateVersionVariable](schemas.md#codersdktemplateversionvariable) |

<h3 id="get-template-variables-by-template-version-responseschema">Response Schema</h3>

Status Code **200**

| Name              | Type    | Required | Restrictions | Description |
|-------------------|---------|----------|--------------|-------------|
| `[array item]`    | array   | false    |              |             |
| `» default_value` | string  | false    |              |             |
| `» description`   | string  | false    |              |             |
| `» name`          | string  | false    |              |             |
| `» required`      | boolean | false    |              |             |
| `» sensitive`     | boolean | false    |              |             |
| `» type`          | string  | false    |              |             |
| `» value`         | string  | false    |              |             |

#### Enumerated Values

| Property | Value(s)                   |
|----------|----------------------------|
| `type`   | `bool`, `number`, `string` |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Users

Source: https://coder.com/docs/reference/api/users

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get users

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users`

### Parameters

| Name       | In    | Type         | Required | Description  |
|------------|-------|--------------|----------|--------------|
| `q`        | query | string       | false    | Search query |
| `after_id` | query | string(uuid) | false    | After ID     |
| `limit`    | query | integer      | false    | Page limit   |
| `offset`   | query | integer      | false    | Page offset  |

### Example responses

> 200 Response

```json
{
  "count": 0,
  "users": [
    {
      "avatar_url": "http://example.com",
      "created_at": "2019-08-24T14:15:22Z",
      "email": "user@example.com",
      "has_ai_seat": true,
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_service_account": true,
      "last_seen_at": "2019-08-24T14:15:22Z",
      "login_type": "",
      "name": "string",
      "organization_ids": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "roles": [
        {
          "display_name": "string",
          "name": "string",
          "organization_id": "string"
        }
      ],
      "status": "active",
      "theme_preference": "string",
      "updated_at": "2019-08-24T14:15:22Z",
      "username": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                           |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GetUsersResponse](schemas.md#codersdkgetusersresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create new user

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users`

> Body parameter

```json
{
  "email": "user@example.com",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "password": "string",
  "roles": [
    "string"
  ],
  "service_account": true,
  "user_status": "active",
  "username": "string"
}
```

### Parameters

| Name   | In   | Type                                                               | Required | Description         |
|--------|------|--------------------------------------------------------------------|----------|---------------------|
| `body` | body | [codersdk.CreateUserRequest](schemas.md#codersdkcreateuserrequest) | true     | Create user request |

### Example responses

> 201 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                   |
|--------|--------------------------------------------------------------|-------------|------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get authentication methods

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/authmethods \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/authmethods`

### Example responses

> 200 Response

```json
{
  "github": {
    "default_provider_configured": true,
    "enabled": true
  },
  "oidc": {
    "enabled": true,
    "iconUrl": "string",
    "signInText": "string"
  },
  "password": {
    "enabled": true
  },
  "terms_of_service_url": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                 |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.AuthMethods](schemas.md#codersdkauthmethods) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Check initial user created

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/first \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/first`

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create initial user

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/first \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/first`

> Body parameter

```json
{
  "email": "string",
  "name": "string",
  "onboarding_info": {
    "newsletter_marketing": true,
    "newsletter_releases": true
  },
  "password": "string",
  "trial": true,
  "trial_info": {
    "company_name": "string",
    "country": "string",
    "developers": "string",
    "first_name": "string",
    "job_title": "string",
    "last_name": "string",
    "phone_number": "string"
  },
  "username": "string"
}
```

### Parameters

| Name   | In   | Type                                                                         | Required | Description        |
|--------|------|------------------------------------------------------------------------------|----------|--------------------|
| `body` | body | [codersdk.CreateFirstUserRequest](schemas.md#codersdkcreatefirstuserrequest) | true     | First user request |

### Example responses

> 201 Response

```json
{
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                                         |
|--------|--------------------------------------------------------------|-------------|--------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.CreateFirstUserResponse](schemas.md#codersdkcreatefirstuserresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Log out user

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/logout \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/logout`

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## OAuth 2.0 GitHub Callback

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/oauth2/github/callback \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/oauth2/github/callback`

### Responses

| Status | Meaning                                                                 | Description        | Schema |
|--------|-------------------------------------------------------------------------|--------------------|--------|
| 307    | [Temporary Redirect](https://tools.ietf.org/html/rfc7231#section-6.4.7) | Temporary Redirect |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get Github device auth

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/oauth2/github/device \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/oauth2/github/device`

### Example responses

> 200 Response

```json
{
  "device_code": "string",
  "expires_in": 0,
  "interval": 0,
  "user_code": "string",
  "verification_uri": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                               |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ExternalAuthDevice](schemas.md#codersdkexternalauthdevice) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get OIDC claims for the authenticated user

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/oidc-claims \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/oidc-claims`

### Example responses

> 200 Response

```json
{
  "claims": {}
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                               |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.OIDCClaimsResponse](schemas.md#codersdkoidcclaimsresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## OpenID Connect Callback

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/oidc/callback \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/oidc/callback`

### Responses

| Status | Meaning                                                                 | Description        | Schema |
|--------|-------------------------------------------------------------------------|--------------------|--------|
| 307    | [Temporary Redirect](https://tools.ietf.org/html/rfc7231#section-6.4.7) | Temporary Redirect |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user by name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}`

### Parameters

| Name   | In   | Type   | Required | Description              |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true     | User ID, username, or me |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete user

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/users/{user} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/users/{user}`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Responses

| Status | Meaning                                                 | Description | Schema |
|--------|---------------------------------------------------------|-------------|--------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user appearance settings

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/appearance \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/appearance`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "terminal_font": "",
  "theme_dark": "string",
  "theme_light": "string",
  "theme_mode": "",
  "theme_preference": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                       |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserAppearanceSettings](schemas.md#codersdkuserappearancesettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user appearance settings

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/appearance \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/appearance`

> Body parameter

```json
{
  "terminal_font": "",
  "theme_dark": "light",
  "theme_light": "light",
  "theme_mode": "sync",
  "theme_preference": "string"
}
```

### Parameters

| Name   | In   | Type                                                                                                   | Required | Description             |
|--------|------|--------------------------------------------------------------------------------------------------------|----------|-------------------------|
| `user` | path | string                                                                                                 | true     | User ID, name, or me    |
| `body` | body | [codersdk.UpdateUserAppearanceSettingsRequest](schemas.md#codersdkupdateuserappearancesettingsrequest) | true     | New appearance settings |

### Example responses

> 200 Response

```json
{
  "terminal_font": "",
  "theme_dark": "string",
  "theme_light": "string",
  "theme_mode": "",
  "theme_preference": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                       |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserAppearanceSettings](schemas.md#codersdkuserappearancesettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get autofill build parameters for user

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/autofill-parameters?template_id=string \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/autofill-parameters`

### Parameters

| Name          | In    | Type   | Required | Description              |
|---------------|-------|--------|----------|--------------------------|
| `user`        | path  | string | true     | User ID, username, or me |
| `template_id` | query | string | true     | Template ID              |

### Example responses

> 200 Response

```json
[
  {
    "name": "string",
    "value": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                              |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.UserParameter](schemas.md#codersdkuserparameter) |

<h3 id="get-autofill-build-parameters-for-user-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type   | Required | Restrictions | Description |
|----------------|--------|----------|--------------|-------------|
| `[array item]` | array  | false    |              |             |
| `» name`       | string | false    |              |             |
| `» value`      | string | false    |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user Git SSH key

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/gitsshkey \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/gitsshkey`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "public_key": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                             |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GitSSHKey](schemas.md#codersdkgitsshkey) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Regenerate user SSH key

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/gitsshkey \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/gitsshkey`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "public_key": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                             |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.GitSSHKey](schemas.md#codersdkgitsshkey) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create new session key

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/{user}/keys \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/{user}/keys`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 201 Response

```json
{
  "key": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                                       |
|--------|--------------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.GenerateAPIKeyResponse](schemas.md#codersdkgenerateapikeyresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user tokens

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/keys/tokens \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/keys/tokens`

### Parameters

| Name              | In    | Type    | Required | Description                        |
|-------------------|-------|---------|----------|------------------------------------|
| `user`            | path  | string  | true     | User ID, name, or me               |
| `include_expired` | query | boolean | false    | Include expired tokens in the list |

### Example responses

> 200 Response

```json
[
  {
    "allow_list": [
      {
        "id": "string",
        "type": "*"
      }
    ],
    "created_at": "2019-08-24T14:15:22Z",
    "expires_at": "2019-08-24T14:15:22Z",
    "id": "string",
    "last_used": "2019-08-24T14:15:22Z",
    "lifetime_seconds": 0,
    "login_type": "password",
    "scope": "all",
    "scopes": [
      "all"
    ],
    "token_name": "string",
    "updated_at": "2019-08-24T14:15:22Z",
    "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.APIKey](schemas.md#codersdkapikey) |

<h3 id="get-user-tokens-responseschema">Response Schema</h3>

Status Code **200**

| Name                 | Type                                                     | Required | Restrictions | Description                     |
|----------------------|----------------------------------------------------------|----------|--------------|---------------------------------|
| `[array item]`       | array                                                    | false    |              |                                 |
| `» allow_list`       | array                                                    | false    |              |                                 |
| `»» id`              | string                                                   | false    |              |                                 |
| `»» type`            | [codersdk.RBACResource](schemas.md#codersdkrbacresource) | false    |              |                                 |
| `» created_at`       | string(date-time)                                        | true     |              |                                 |
| `» expires_at`       | string(date-time)                                        | true     |              |                                 |
| `» id`               | string                                                   | true     |              |                                 |
| `» last_used`        | string(date-time)                                        | true     |              |                                 |
| `» lifetime_seconds` | integer                                                  | true     |              |                                 |
| `» login_type`       | [codersdk.LoginType](schemas.md#codersdklogintype)       | true     |              |                                 |
| `» scope`            | [codersdk.APIKeyScope](schemas.md#codersdkapikeyscope)   | false    |              | Deprecated: use Scopes instead. |
| `» scopes`           | array                                                    | false    |              |                                 |
| `» token_name`       | string                                                   | true     |              |                                 |
| `» updated_at`       | string(date-time)                                        | true     |              |                                 |
| `» user_id`          | string(uuid)                                             | true     |              |                                 |

#### Enumerated Values

| Property     | Value(s)                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
|--------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `type`       | `*`, `ai_gateway_key`, `ai_model_price`, `ai_provider`, `ai_seat`, `aibridge_interception`, `api_key`, `assign_org_role`, `assign_role`, `audit_log`, `boundary_log`, `boundary_usage`, `chat`, `chat_model_config`, `connection_log`, `crypto_key`, `debug_info`, `deployment_config`, `deployment_stats`, `file`, `group`, `group_member`, `idpsync_settings`, `inbox_notification`, `license`, `mcp_server_config`, `notification_message`, `notification_preference`, `notification_template`, `oauth2_app`, `oauth2_app_code_token`, `oauth2_app_secret`, `organization`, `organization_member`, `prebuilt_workspace`, `provisioner_daemon`, `provisioner_jobs`, `replicas`, `system`, `tailnet_coordinator`, `template`, `usage_event`, `user`, `user_secret`, `user_skill`, `webpush_subscription`, `workspace`, `workspace_agent_devcontainers`, `workspace_agent_resource_monitor`, `workspace_build_orchestration`, `workspace_dormant`, `workspace_proxy` |
| `login_type` | `github`, `oidc`, `password`, `token`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `scope`      | `all`, `application_connect`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create token API key

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/{user}/keys/tokens \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/{user}/keys/tokens`

> Body parameter

```json
{
  "allow_list": [
    {
      "id": "string",
      "type": "*"
    }
  ],
  "lifetime": 0,
  "scope": "all",
  "scopes": [
    "all"
  ],
  "token_name": "string"
}
```

### Parameters

| Name   | In   | Type                                                                 | Required | Description          |
|--------|------|----------------------------------------------------------------------|----------|----------------------|
| `user` | path | string                                                               | true     | User ID, name, or me |
| `body` | body | [codersdk.CreateTokenRequest](schemas.md#codersdkcreatetokenrequest) | true     | Create token request |

### Example responses

> 201 Response

```json
{
  "key": "string"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                                                       |
|--------|--------------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.GenerateAPIKeyResponse](schemas.md#codersdkgenerateapikeyresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get API key by token name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/keys/tokens/{keyname} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/keys/tokens/{keyname}`

### Parameters

| Name      | In   | Type           | Required | Description          |
|-----------|------|----------------|----------|----------------------|
| `user`    | path | string         | true     | User ID, name, or me |
| `keyname` | path | string(string) | true     | Key Name             |

### Example responses

> 200 Response

```json
{
  "allow_list": [
    {
      "id": "string",
      "type": "*"
    }
  ],
  "created_at": "2019-08-24T14:15:22Z",
  "expires_at": "2019-08-24T14:15:22Z",
  "id": "string",
  "last_used": "2019-08-24T14:15:22Z",
  "lifetime_seconds": 0,
  "login_type": "password",
  "scope": "all",
  "scopes": [
    "all"
  ],
  "token_name": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.APIKey](schemas.md#codersdkapikey) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get API key by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/keys/{keyid} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/keys/{keyid}`

### Parameters

| Name    | In   | Type           | Required | Description          |
|---------|------|----------------|----------|----------------------|
| `user`  | path | string         | true     | User ID, name, or me |
| `keyid` | path | string(string) | true     | Key ID               |

### Example responses

> 200 Response

```json
{
  "allow_list": [
    {
      "id": "string",
      "type": "*"
    }
  ],
  "created_at": "2019-08-24T14:15:22Z",
  "expires_at": "2019-08-24T14:15:22Z",
  "id": "string",
  "last_used": "2019-08-24T14:15:22Z",
  "lifetime_seconds": 0,
  "login_type": "password",
  "scope": "all",
  "scopes": [
    "all"
  ],
  "token_name": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                       |
|--------|---------------------------------------------------------|-------------|----------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.APIKey](schemas.md#codersdkapikey) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Delete API key

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/users/{user}/keys/{keyid} \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/users/{user}/keys/{keyid}`

### Parameters

| Name    | In   | Type           | Required | Description          |
|---------|------|----------------|----------|----------------------|
| `user`  | path | string         | true     | User ID, name, or me |
| `keyid` | path | string(string) | true     | Key ID               |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Expire API key

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/keys/{keyid}/expire \
  -H 'Accept: */*' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/keys/{keyid}/expire`

### Parameters

| Name    | In   | Type           | Required | Description          |
|---------|------|----------------|----------|----------------------|
| `user`  | path | string         | true     | User ID, name, or me |
| `keyid` | path | string(string) | true     | Key ID               |

### Example responses

> 404 Response

### Responses

| Status | Meaning                                                                    | Description           | Schema                                           |
|--------|----------------------------------------------------------------------------|-----------------------|--------------------------------------------------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5)            | No Content            |                                                  |
| 404    | [Not Found](https://tools.ietf.org/html/rfc7231#section-6.5.4)             | Not Found             | [codersdk.Response](schemas.md#codersdkresponse) |
| 500    | [Internal Server Error](https://tools.ietf.org/html/rfc7231#section-6.6.1) | Internal Server Error | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user login type

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/login-type \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/login-type`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "login_type": ""
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                     |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserLoginType](schemas.md#codersdkuserlogintype) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get organizations by user

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/organizations \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/organizations`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
[
  {
    "created_at": "2019-08-24T14:15:22Z",
    "default_org_member_roles": [
      "string"
    ],
    "description": "string",
    "display_name": "string",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "is_default": true,
    "name": "string",
    "updated_at": "2019-08-24T14:15:22Z"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                            |
|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.Organization](schemas.md#codersdkorganization) |

<h3 id="get-organizations-by-user-responseschema">Response Schema</h3>

Status Code **200**

| Name                         | Type              | Required | Restrictions | Description                                                                                                                                     |
|------------------------------|-------------------|----------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------|
| `[array item]`               | array             | false    |              |                                                                                                                                                 |
| `» created_at`               | string(date-time) | true     |              |                                                                                                                                                 |
| `» default_org_member_roles` | array             | false    |              | Default org member roles are unioned into every member's effective roles at request time. Changes propagate to all members on the next request. |
| `» description`              | string            | false    |              |                                                                                                                                                 |
| `» display_name`             | string            | false    |              |                                                                                                                                                 |
| `» icon`                     | string            | false    |              |                                                                                                                                                 |
| `» id`                       | string(uuid)      | true     |              |                                                                                                                                                 |
| `» is_default`               | boolean           | true     |              |                                                                                                                                                 |
| `» name`                     | string            | false    |              |                                                                                                                                                 |
| `» updated_at`               | string(date-time) | true     |              |                                                                                                                                                 |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get organization by user and organization name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/organizations/{organizationname} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/organizations/{organizationname}`

### Parameters

| Name               | In   | Type   | Required | Description          |
|--------------------|------|--------|----------|----------------------|
| `user`             | path | string | true     | User ID, name, or me |
| `organizationname` | path | string | true     | Organization name    |

### Example responses

> 200 Response

```json
{
  "created_at": "2019-08-24T14:15:22Z",
  "default_org_member_roles": [
    "string"
  ],
  "description": "string",
  "display_name": "string",
  "icon": "string",
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_default": true,
  "name": "string",
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Organization](schemas.md#codersdkorganization) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user password

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/password \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/password`

> Body parameter

```json
{
  "old_password": "string",
  "password": "string"
}
```

### Parameters

| Name   | In   | Type                                                                               | Required | Description             |
|--------|------|------------------------------------------------------------------------------------|----------|-------------------------|
| `user` | path | string                                                                             | true     | User ID, name, or me    |
| `body` | body | [codersdk.UpdateUserPasswordRequest](schemas.md#codersdkupdateuserpasswordrequest) | true     | Update password request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user preference settings

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/preferences \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/preferences`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "agent_chat_send_shortcut": "enter",
  "code_diff_display_mode": "auto",
  "collapse_assistant_steps": true,
  "shell_tool_display_mode": "auto",
  "thinking_display_mode": "auto"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                       |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserPreferenceSettings](schemas.md#codersdkuserpreferencesettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user preference settings

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/preferences \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/preferences`

> Body parameter

```json
{
  "agent_chat_send_shortcut": "enter",
  "code_diff_display_mode": "auto",
  "collapse_assistant_steps": true,
  "shell_tool_display_mode": "auto",
  "thinking_display_mode": "auto"
}
```

### Parameters

| Name   | In   | Type                                                                                                   | Required | Description             |
|--------|------|--------------------------------------------------------------------------------------------------------|----------|-------------------------|
| `user` | path | string                                                                                                 | true     | User ID, name, or me    |
| `body` | body | [codersdk.UpdateUserPreferenceSettingsRequest](schemas.md#codersdkupdateuserpreferencesettingsrequest) | true     | New preference settings |

### Example responses

> 200 Response

```json
{
  "agent_chat_send_shortcut": "enter",
  "code_diff_display_mode": "auto",
  "collapse_assistant_steps": true,
  "shell_tool_display_mode": "auto",
  "thinking_display_mode": "auto"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                       |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.UserPreferenceSettings](schemas.md#codersdkuserpreferencesettings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update user profile

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/profile \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/profile`

> Body parameter

```json
{
  "avatar_url": "http://example.com",
  "name": "string",
  "username": "string"
}
```

### Parameters

| Name   | In   | Type                                                                             | Required | Description          |
|--------|------|----------------------------------------------------------------------------------|----------|----------------------|
| `user` | path | string                                                                           | true     | User ID, name, or me |
| `body` | body | [codersdk.UpdateUserProfileRequest](schemas.md#codersdkupdateuserprofilerequest) | true     | Updated profile      |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get user roles

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/roles \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/roles`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Assign role to user

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/roles \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/roles`

> Body parameter

```json
{
  "roles": [
    "string"
  ]
}
```

### Parameters

| Name   | In   | Type                                                   | Required | Description          |
|--------|------|--------------------------------------------------------|----------|----------------------|
| `user` | path | string                                                 | true     | User ID, name, or me |
| `body` | body | [codersdk.UpdateRoles](schemas.md#codersdkupdateroles) | true     | Update roles request |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Activate user account

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/activate \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/status/activate`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Suspend user account

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/suspend \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/users/{user}/status/suspend`

### Parameters

| Name   | In   | Type   | Required | Description          |
|--------|------|--------|----------|----------------------|
| `user` | path | string | true     | User ID, name, or me |

### Example responses

> 200 Response

```json
{
  "avatar_url": "http://example.com",
  "created_at": "2019-08-24T14:15:22Z",
  "email": "user@example.com",
  "has_ai_seat": true,
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_service_account": true,
  "last_seen_at": "2019-08-24T14:15:22Z",
  "login_type": "",
  "name": "string",
  "organization_ids": [
    "497f6eca-6276-4993-bfeb-53cbbbba6f08"
  ],
  "roles": [
    {
      "display_name": "string",
      "name": "string",
      "organization_id": "string"
    }
  ],
  "status": "active",
  "theme_preference": "string",
  "updated_at": "2019-08-24T14:15:22Z",
  "username": "string"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                   |
|--------|---------------------------------------------------------|-------------|------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.User](schemas.md#codersdkuser) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# WorkspaceProxies

Source: https://coder.com/docs/reference/api/workspaceproxies

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Get site-wide regions for workspace connections

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/regions \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/regions`

### Example responses

> 200 Response

```json
{
  "regions": [
    {
      "display_name": "string",
      "healthy": true,
      "icon_url": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "path_app_url": "string",
      "wildcard_hostname": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                                         |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.RegionsResponse-codersdk_Region](schemas.md#codersdkregionsresponse-codersdk_region) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Workspaces

Source: https://coder.com/docs/reference/api/workspaces

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Create user workspace by organization

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/members/{user}/workspaces \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/organizations/{organization}/members/{user}/workspaces`

Create a new workspace using a template. The request must
specify either the Template ID or the Template Version ID,
not both. If the Template ID is specified, the active version
of the template will be used.

> Body parameter

```json
{
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "name": "string",
  "rich_parameter_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "ttl_ms": 0
}
```

### Parameters

| Name           | In   | Type                                                                         | Required | Description              |
|----------------|------|------------------------------------------------------------------------------|----------|--------------------------|
| `organization` | path | string(uuid)                                                                 | true     | Organization ID          |
| `user`         | path | string                                                                       | true     | Username, UUID, or me    |
| `body`         | body | [codersdk.CreateWorkspaceRequest](schemas.md#codersdkcreateworkspacerequest) | true     | Create workspace request |

### Example responses

> 201 Response

```json
{
  "allow_renames": true,
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "deleting_at": "2019-08-24T14:15:22Z",
  "dormant_at": "2019-08-24T14:15:22Z",
  "favorite": true,
  "health": {
    "failing_agents": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "healthy": false
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_prebuild": true,
  "last_used_at": "2019-08-24T14:15:22Z",
  "latest_app_status": {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
    "created_at": "2019-08-24T14:15:22Z",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "message": "string",
    "needs_user_attention": true,
    "state": "working",
    "uri": "string",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  },
  "latest_build": {
    "build_number": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "deadline": "2019-08-24T14:15:22Z",
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "initiator_name": "string",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "max_deadline": "2019-08-24T14:15:22Z",
    "reason": "initiator",
    "resources": [
      {
        "agents": [
          {
            "api_version": "string",
            "apps": [
              {
                "command": "string",
                "display_name": "string",
                "external": true,
                "group": "string",
                "health": "disabled",
                "healthcheck": {
                  "interval": 0,
                  "threshold": 0,
                  "url": "string"
                },
                "hidden": true,
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "open_in": "slim-window",
                "sharing_level": "owner",
                "slug": "string",
                "statuses": [
                  {
                    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                    "created_at": "2019-08-24T14:15:22Z",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "message": "string",
                    "needs_user_attention": true,
                    "state": "working",
                    "uri": "string",
                    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                  }
                ],
                "subdomain": true,
                "subdomain_name": "string",
                "tooltip": "string",
                "url": "string"
              }
            ],
            "architecture": "string",
            "connection_timeout_seconds": 0,
            "created_at": "2019-08-24T14:15:22Z",
            "directory": "string",
            "disconnected_at": "2019-08-24T14:15:22Z",
            "display_apps": [
              "vscode"
            ],
            "environment_variables": {
              "property1": "string",
              "property2": "string"
            },
            "expanded_directory": "string",
            "first_connected_at": "2019-08-24T14:15:22Z",
            "health": {
              "healthy": false,
              "reason": "agent has lost connection"
            },
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "instance_id": "string",
            "last_connected_at": "2019-08-24T14:15:22Z",
            "latency": {
              "property1": {
                "latency_ms": 0,
                "preferred": true
              },
              "property2": {
                "latency_ms": 0,
                "preferred": true
              }
            },
            "lifecycle_state": "created",
            "log_sources": [
              {
                "created_at": "2019-08-24T14:15:22Z",
                "display_name": "string",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
              }
            ],
            "logs_length": 0,
            "logs_overflowed": true,
            "metadata": [
              {
                "description": {
                  "display_name": "string",
                  "interval": 0,
                  "key": "string",
                  "script": "string",
                  "timeout": 0
                },
                "result": {
                  "age": 0,
                  "collected_at": "2019-08-24T14:15:22Z",
                  "error": "string",
                  "value": "string"
                }
              }
            ],
            "name": "string",
            "operating_system": "string",
            "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
            "ready_at": "2019-08-24T14:15:22Z",
            "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
            "scripts": [
              {
                "cron": "string",
                "display_name": "string",
                "exit_code": 0,
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "log_path": "string",
                "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                "run_on_start": true,
                "run_on_stop": true,
                "script": "string",
                "start_blocks_login": true,
                "status": "ok",
                "timeout": 0
              }
            ],
            "started_at": "2019-08-24T14:15:22Z",
            "startup_script_behavior": "blocking",
            "status": "connecting",
            "subsystems": [
              "envbox"
            ],
            "troubleshooting_url": "string",
            "updated_at": "2019-08-24T14:15:22Z",
            "version": "string"
          }
        ],
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "hide": true,
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
        "metadata": [
          {
            "key": "string",
            "sensitive": true,
            "value": "string"
          }
        ],
        "name": "string",
        "type": "string",
        "workspace_transition": "start"
      }
    ],
    "status": "pending",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_name": "string",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start",
    "updated_at": "2019-08-24T14:15:22Z",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string",
    "workspace_owner_avatar_url": "string",
    "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
    "workspace_owner_name": "string"
  },
  "name": "string",
  "next_start_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "outdated": true,
  "owner_avatar_url": "string",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "shared_with": [
    {
      "actor_type": "group",
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "roles": [
        "admin"
      ]
    }
  ],
  "template_active_version_id": "b0da9c29-67d8-4c87-888c-bafe356f7f3c",
  "template_allow_user_cancel_workspace_jobs": true,
  "template_display_name": "string",
  "template_icon": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_name": "string",
  "template_require_active_version": true,
  "template_use_classic_parameter_flow": true,
  "ttl_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                             |
|--------|--------------------------------------------------------------|-------------|----------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.Workspace](schemas.md#codersdkworkspace) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get users available for workspace creation

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/members/{user}/workspaces/available-users \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/organizations/{organization}/members/{user}/workspaces/available-users`

### Parameters

| Name           | In    | Type         | Required | Description           |
|----------------|-------|--------------|----------|-----------------------|
| `organization` | path  | string(uuid) | true     | Organization ID       |
| `user`         | path  | string       | true     | User ID, name, or me  |
| `q`            | query | string       | false    | Search query          |
| `limit`        | query | integer      | false    | Limit results         |
| `offset`       | query | integer      | false    | Offset for pagination |

### Example responses

> 200 Response

```json
[
  {
    "avatar_url": "http://example.com",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "name": "string",
    "username": "string"
  }
]
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                          |
|--------|---------------------------------------------------------|-------------|-----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | array of [codersdk.MinimalUser](schemas.md#codersdkminimaluser) |

<h3 id="get-users-available-for-workspace-creation-responseschema">Response Schema</h3>

Status Code **200**

| Name           | Type         | Required | Restrictions | Description |
|----------------|--------------|----------|--------------|-------------|
| `[array item]` | array        | false    |              |             |
| `» avatar_url` | string(uri)  | false    |              |             |
| `» id`         | string(uuid) | true     |              |             |
| `» name`       | string       | false    |              |             |
| `» username`   | string       | true     |              |             |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace metadata by user and workspace name

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacename} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/users/{user}/workspace/{workspacename}`

### Parameters

| Name              | In    | Type    | Required | Description                                                                                                                    |
|-------------------|-------|---------|----------|--------------------------------------------------------------------------------------------------------------------------------|
| `user`            | path  | string  | true     | User ID, name, or me                                                                                                           |
| `workspacename`   | path  | string  | true     | Workspace name                                                                                                                 |
| `include_deleted` | query | boolean | false    | Return data instead of HTTP 404 if the workspace is deleted                                                                    |
| `include_related` | query | string  | false    | Comma-separated list of related data to include (e.g. `template,latest_build.resources.agents.*`). Omit to include everything. |

### Example responses

> 200 Response

```json
{
  "allow_renames": true,
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "deleting_at": "2019-08-24T14:15:22Z",
  "dormant_at": "2019-08-24T14:15:22Z",
  "favorite": true,
  "health": {
    "failing_agents": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "healthy": false
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_prebuild": true,
  "last_used_at": "2019-08-24T14:15:22Z",
  "latest_app_status": {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
    "created_at": "2019-08-24T14:15:22Z",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "message": "string",
    "needs_user_attention": true,
    "state": "working",
    "uri": "string",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  },
  "latest_build": {
    "build_number": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "deadline": "2019-08-24T14:15:22Z",
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "initiator_name": "string",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "max_deadline": "2019-08-24T14:15:22Z",
    "reason": "initiator",
    "resources": [
      {
        "agents": [
          {
            "api_version": "string",
            "apps": [
              {
                "command": "string",
                "display_name": "string",
                "external": true,
                "group": "string",
                "health": "disabled",
                "healthcheck": {
                  "interval": 0,
                  "threshold": 0,
                  "url": "string"
                },
                "hidden": true,
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "open_in": "slim-window",
                "sharing_level": "owner",
                "slug": "string",
                "statuses": [
                  {
                    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                    "created_at": "2019-08-24T14:15:22Z",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "message": "string",
                    "needs_user_attention": true,
                    "state": "working",
                    "uri": "string",
                    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                  }
                ],
                "subdomain": true,
                "subdomain_name": "string",
                "tooltip": "string",
                "url": "string"
              }
            ],
            "architecture": "string",
            "connection_timeout_seconds": 0,
            "created_at": "2019-08-24T14:15:22Z",
            "directory": "string",
            "disconnected_at": "2019-08-24T14:15:22Z",
            "display_apps": [
              "vscode"
            ],
            "environment_variables": {
              "property1": "string",
              "property2": "string"
            },
            "expanded_directory": "string",
            "first_connected_at": "2019-08-24T14:15:22Z",
            "health": {
              "healthy": false,
              "reason": "agent has lost connection"
            },
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "instance_id": "string",
            "last_connected_at": "2019-08-24T14:15:22Z",
            "latency": {
              "property1": {
                "latency_ms": 0,
                "preferred": true
              },
              "property2": {
                "latency_ms": 0,
                "preferred": true
              }
            },
            "lifecycle_state": "created",
            "log_sources": [
              {
                "created_at": "2019-08-24T14:15:22Z",
                "display_name": "string",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
              }
            ],
            "logs_length": 0,
            "logs_overflowed": true,
            "metadata": [
              {
                "description": {
                  "display_name": "string",
                  "interval": 0,
                  "key": "string",
                  "script": "string",
                  "timeout": 0
                },
                "result": {
                  "age": 0,
                  "collected_at": "2019-08-24T14:15:22Z",
                  "error": "string",
                  "value": "string"
                }
              }
            ],
            "name": "string",
            "operating_system": "string",
            "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
            "ready_at": "2019-08-24T14:15:22Z",
            "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
            "scripts": [
              {
                "cron": "string",
                "display_name": "string",
                "exit_code": 0,
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "log_path": "string",
                "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                "run_on_start": true,
                "run_on_stop": true,
                "script": "string",
                "start_blocks_login": true,
                "status": "ok",
                "timeout": 0
              }
            ],
            "started_at": "2019-08-24T14:15:22Z",
            "startup_script_behavior": "blocking",
            "status": "connecting",
            "subsystems": [
              "envbox"
            ],
            "troubleshooting_url": "string",
            "updated_at": "2019-08-24T14:15:22Z",
            "version": "string"
          }
        ],
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "hide": true,
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
        "metadata": [
          {
            "key": "string",
            "sensitive": true,
            "value": "string"
          }
        ],
        "name": "string",
        "type": "string",
        "workspace_transition": "start"
      }
    ],
    "status": "pending",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_name": "string",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start",
    "updated_at": "2019-08-24T14:15:22Z",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string",
    "workspace_owner_avatar_url": "string",
    "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
    "workspace_owner_name": "string"
  },
  "name": "string",
  "next_start_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "outdated": true,
  "owner_avatar_url": "string",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "shared_with": [
    {
      "actor_type": "group",
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "roles": [
        "admin"
      ]
    }
  ],
  "template_active_version_id": "b0da9c29-67d8-4c87-888c-bafe356f7f3c",
  "template_allow_user_cancel_workspace_jobs": true,
  "template_display_name": "string",
  "template_icon": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_name": "string",
  "template_require_active_version": true,
  "template_use_classic_parameter_flow": true,
  "ttl_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                             |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Workspace](schemas.md#codersdkworkspace) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Create user workspace

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/{user}/workspaces \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/users/{user}/workspaces`

Create a new workspace using a template. The request must
specify either the Template ID or the Template Version ID,
not both. If the Template ID is specified, the active version
of the template will be used.

> Body parameter

```json
{
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "name": "string",
  "rich_parameter_values": [
    {
      "name": "string",
      "value": "string"
    }
  ],
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
  "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
  "ttl_ms": 0
}
```

### Parameters

| Name   | In   | Type                                                                         | Required | Description              |
|--------|------|------------------------------------------------------------------------------|----------|--------------------------|
| `user` | path | string                                                                       | true     | Username, UUID, or me    |
| `body` | body | [codersdk.CreateWorkspaceRequest](schemas.md#codersdkcreateworkspacerequest) | true     | Create workspace request |

### Example responses

> 201 Response

```json
{
  "allow_renames": true,
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "deleting_at": "2019-08-24T14:15:22Z",
  "dormant_at": "2019-08-24T14:15:22Z",
  "favorite": true,
  "health": {
    "failing_agents": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "healthy": false
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_prebuild": true,
  "last_used_at": "2019-08-24T14:15:22Z",
  "latest_app_status": {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
    "created_at": "2019-08-24T14:15:22Z",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "message": "string",
    "needs_user_attention": true,
    "state": "working",
    "uri": "string",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  },
  "latest_build": {
    "build_number": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "deadline": "2019-08-24T14:15:22Z",
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "initiator_name": "string",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "max_deadline": "2019-08-24T14:15:22Z",
    "reason": "initiator",
    "resources": [
      {
        "agents": [
          {
            "api_version": "string",
            "apps": [
              {
                "command": "string",
                "display_name": "string",
                "external": true,
                "group": "string",
                "health": "disabled",
                "healthcheck": {
                  "interval": 0,
                  "threshold": 0,
                  "url": "string"
                },
                "hidden": true,
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "open_in": "slim-window",
                "sharing_level": "owner",
                "slug": "string",
                "statuses": [
                  {
                    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                    "created_at": "2019-08-24T14:15:22Z",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "message": "string",
                    "needs_user_attention": true,
                    "state": "working",
                    "uri": "string",
                    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                  }
                ],
                "subdomain": true,
                "subdomain_name": "string",
                "tooltip": "string",
                "url": "string"
              }
            ],
            "architecture": "string",
            "connection_timeout_seconds": 0,
            "created_at": "2019-08-24T14:15:22Z",
            "directory": "string",
            "disconnected_at": "2019-08-24T14:15:22Z",
            "display_apps": [
              "vscode"
            ],
            "environment_variables": {
              "property1": "string",
              "property2": "string"
            },
            "expanded_directory": "string",
            "first_connected_at": "2019-08-24T14:15:22Z",
            "health": {
              "healthy": false,
              "reason": "agent has lost connection"
            },
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "instance_id": "string",
            "last_connected_at": "2019-08-24T14:15:22Z",
            "latency": {
              "property1": {
                "latency_ms": 0,
                "preferred": true
              },
              "property2": {
                "latency_ms": 0,
                "preferred": true
              }
            },
            "lifecycle_state": "created",
            "log_sources": [
              {
                "created_at": "2019-08-24T14:15:22Z",
                "display_name": "string",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
              }
            ],
            "logs_length": 0,
            "logs_overflowed": true,
            "metadata": [
              {
                "description": {
                  "display_name": "string",
                  "interval": 0,
                  "key": "string",
                  "script": "string",
                  "timeout": 0
                },
                "result": {
                  "age": 0,
                  "collected_at": "2019-08-24T14:15:22Z",
                  "error": "string",
                  "value": "string"
                }
              }
            ],
            "name": "string",
            "operating_system": "string",
            "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
            "ready_at": "2019-08-24T14:15:22Z",
            "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
            "scripts": [
              {
                "cron": "string",
                "display_name": "string",
                "exit_code": 0,
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "log_path": "string",
                "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                "run_on_start": true,
                "run_on_stop": true,
                "script": "string",
                "start_blocks_login": true,
                "status": "ok",
                "timeout": 0
              }
            ],
            "started_at": "2019-08-24T14:15:22Z",
            "startup_script_behavior": "blocking",
            "status": "connecting",
            "subsystems": [
              "envbox"
            ],
            "troubleshooting_url": "string",
            "updated_at": "2019-08-24T14:15:22Z",
            "version": "string"
          }
        ],
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "hide": true,
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
        "metadata": [
          {
            "key": "string",
            "sensitive": true,
            "value": "string"
          }
        ],
        "name": "string",
        "type": "string",
        "workspace_transition": "start"
      }
    ],
    "status": "pending",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_name": "string",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start",
    "updated_at": "2019-08-24T14:15:22Z",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string",
    "workspace_owner_avatar_url": "string",
    "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
    "workspace_owner_name": "string"
  },
  "name": "string",
  "next_start_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "outdated": true,
  "owner_avatar_url": "string",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "shared_with": [
    {
      "actor_type": "group",
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "roles": [
        "admin"
      ]
    }
  ],
  "template_active_version_id": "b0da9c29-67d8-4c87-888c-bafe356f7f3c",
  "template_allow_user_cancel_workspace_jobs": true,
  "template_display_name": "string",
  "template_icon": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_name": "string",
  "template_require_active_version": true,
  "template_use_classic_parameter_flow": true,
  "ttl_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                      | Description | Schema                                             |
|--------|--------------------------------------------------------------|-------------|----------------------------------------------------|
| 201    | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created     | [codersdk.Workspace](schemas.md#codersdkworkspace) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## List workspaces

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces`

### Parameters

| Name     | In    | Type    | Required | Description                                                                                                                                                                                                                                                                                                       |
|----------|-------|---------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `q`      | query | string  | false    | Search query in the format `key:value`. Available keys are: owner, template, name, status, has-agent, dormant, last_used_after, last_used_before, has_external_agent, healthy, include_agent_metadata (expands each agent with the named metadata keys rather than filtering; repeat the key for multiple items). |
| `limit`  | query | integer | false    | Page limit                                                                                                                                                                                                                                                                                                        |
| `offset` | query | integer | false    | Page offset                                                                                                                                                                                                                                                                                                       |

### Example responses

> 200 Response

```json
{
  "count": 0,
  "workspaces": [
    {
      "allow_renames": true,
      "automatic_updates": "always",
      "autostart_schedule": "string",
      "created_at": "2019-08-24T14:15:22Z",
      "deleting_at": "2019-08-24T14:15:22Z",
      "dormant_at": "2019-08-24T14:15:22Z",
      "favorite": true,
      "health": {
        "failing_agents": [
          "497f6eca-6276-4993-bfeb-53cbbbba6f08"
        ],
        "healthy": false
      },
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "is_prebuild": true,
      "last_used_at": "2019-08-24T14:15:22Z",
      "latest_app_status": {
        "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
        "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
        "created_at": "2019-08-24T14:15:22Z",
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "message": "string",
        "needs_user_attention": true,
        "state": "working",
        "uri": "string",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
      },
      "latest_build": {
        "build_number": 0,
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "deadline": "2019-08-24T14:15:22Z",
        "has_external_agent": true,
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
        "initiator_name": "string",
        "job": {
          "available_workers": [
            "497f6eca-6276-4993-bfeb-53cbbbba6f08"
          ],
          "canceled_at": "2019-08-24T14:15:22Z",
          "completed_at": "2019-08-24T14:15:22Z",
          "created_at": "2019-08-24T14:15:22Z",
          "error": "string",
          "error_code": "REQUIRED_TEMPLATE_VARIABLES",
          "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
          "input": {
            "error": "string",
            "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
            "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
          },
          "logs_overflowed": true,
          "metadata": {
            "template_display_name": "string",
            "template_icon": "string",
            "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
            "template_name": "string",
            "template_version_name": "string",
            "workspace_build_transition": "start",
            "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
            "workspace_name": "string"
          },
          "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
          "queue_position": 0,
          "queue_size": 0,
          "started_at": "2019-08-24T14:15:22Z",
          "status": "pending",
          "tags": {
            "property1": "string",
            "property2": "string"
          },
          "type": "template_version_import",
          "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
          "worker_name": "string"
        },
        "matched_provisioners": {
          "available": 0,
          "count": 0,
          "most_recently_seen": "2019-08-24T14:15:22Z"
        },
        "max_deadline": "2019-08-24T14:15:22Z",
        "reason": "initiator",
        "resources": [
          {
            "agents": [
              {
                "api_version": "string",
                "apps": [
                  {
                    "command": "string",
                    "display_name": "string",
                    "external": true,
                    "group": "string",
                    "health": "disabled",
                    "healthcheck": {},
                    "hidden": true,
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "open_in": "slim-window",
                    "sharing_level": "owner",
                    "slug": "string",
                    "statuses": [],
                    "subdomain": true,
                    "subdomain_name": "string",
                    "tooltip": "string",
                    "url": "string"
                  }
                ],
                "architecture": "string",
                "connection_timeout_seconds": 0,
                "created_at": "2019-08-24T14:15:22Z",
                "directory": "string",
                "disconnected_at": "2019-08-24T14:15:22Z",
                "display_apps": [
                  "vscode"
                ],
                "environment_variables": {
                  "property1": "string",
                  "property2": "string"
                },
                "expanded_directory": "string",
                "first_connected_at": "2019-08-24T14:15:22Z",
                "health": {
                  "healthy": false,
                  "reason": "agent has lost connection"
                },
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "instance_id": "string",
                "last_connected_at": "2019-08-24T14:15:22Z",
                "latency": {
                  "property1": {
                    "latency_ms": 0,
                    "preferred": true
                  },
                  "property2": {
                    "latency_ms": 0,
                    "preferred": true
                  }
                },
                "lifecycle_state": "created",
                "log_sources": [
                  {
                    "created_at": "2019-08-24T14:15:22Z",
                    "display_name": "string",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
                  }
                ],
                "logs_length": 0,
                "logs_overflowed": true,
                "metadata": [
                  {
                    "description": {},
                    "result": {}
                  }
                ],
                "name": "string",
                "operating_system": "string",
                "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
                "ready_at": "2019-08-24T14:15:22Z",
                "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
                "scripts": [
                  {
                    "cron": "string",
                    "display_name": "string",
                    "exit_code": 0,
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "log_path": "string",
                    "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                    "run_on_start": true,
                    "run_on_stop": true,
                    "script": "string",
                    "start_blocks_login": true,
                    "status": "ok",
                    "timeout": 0
                  }
                ],
                "started_at": "2019-08-24T14:15:22Z",
                "startup_script_behavior": "blocking",
                "status": "connecting",
                "subsystems": [
                  "envbox"
                ],
                "troubleshooting_url": "string",
                "updated_at": "2019-08-24T14:15:22Z",
                "version": "string"
              }
            ],
            "created_at": "2019-08-24T14:15:22Z",
            "daily_cost": 0,
            "hide": true,
            "icon": "string",
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
            "metadata": [
              {
                "key": "string",
                "sensitive": true,
                "value": "string"
              }
            ],
            "name": "string",
            "type": "string",
            "workspace_transition": "start"
          }
        ],
        "status": "pending",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "template_version_name": "string",
        "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
        "transition": "start",
        "updated_at": "2019-08-24T14:15:22Z",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string",
        "workspace_owner_avatar_url": "string",
        "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
        "workspace_owner_name": "string"
      },
      "name": "string",
      "next_start_at": "2019-08-24T14:15:22Z",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "outdated": true,
      "owner_avatar_url": "string",
      "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
      "owner_name": "string",
      "shared_with": [
        {
          "actor_type": "group",
          "avatar_url": "http://example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "name": "string",
          "roles": [
            "admin"
          ]
        }
      ],
      "template_active_version_id": "b0da9c29-67d8-4c87-888c-bafe356f7f3c",
      "template_allow_user_cancel_workspace_jobs": true,
      "template_display_name": "string",
      "template_icon": "string",
      "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
      "template_name": "string",
      "template_require_active_version": true,
      "template_use_classic_parameter_flow": true,
      "ttl_ms": 0,
      "updated_at": "2019-08-24T14:15:22Z"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                               |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspacesResponse](schemas.md#codersdkworkspacesresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace metadata by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}`

### Parameters

| Name              | In    | Type         | Required | Description                                                                                                                    |
|-------------------|-------|--------------|----------|--------------------------------------------------------------------------------------------------------------------------------|
| `workspace`       | path  | string(uuid) | true     | Workspace ID                                                                                                                   |
| `include_deleted` | query | boolean      | false    | Return data instead of HTTP 404 if the workspace is deleted                                                                    |
| `include_related` | query | string       | false    | Comma-separated list of related data to include (e.g. `template,latest_build.resources.agents.*`). Omit to include everything. |

### Example responses

> 200 Response

```json
{
  "allow_renames": true,
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "deleting_at": "2019-08-24T14:15:22Z",
  "dormant_at": "2019-08-24T14:15:22Z",
  "favorite": true,
  "health": {
    "failing_agents": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "healthy": false
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_prebuild": true,
  "last_used_at": "2019-08-24T14:15:22Z",
  "latest_app_status": {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
    "created_at": "2019-08-24T14:15:22Z",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "message": "string",
    "needs_user_attention": true,
    "state": "working",
    "uri": "string",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  },
  "latest_build": {
    "build_number": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "deadline": "2019-08-24T14:15:22Z",
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "initiator_name": "string",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "max_deadline": "2019-08-24T14:15:22Z",
    "reason": "initiator",
    "resources": [
      {
        "agents": [
          {
            "api_version": "string",
            "apps": [
              {
                "command": "string",
                "display_name": "string",
                "external": true,
                "group": "string",
                "health": "disabled",
                "healthcheck": {
                  "interval": 0,
                  "threshold": 0,
                  "url": "string"
                },
                "hidden": true,
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "open_in": "slim-window",
                "sharing_level": "owner",
                "slug": "string",
                "statuses": [
                  {
                    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                    "created_at": "2019-08-24T14:15:22Z",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "message": "string",
                    "needs_user_attention": true,
                    "state": "working",
                    "uri": "string",
                    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                  }
                ],
                "subdomain": true,
                "subdomain_name": "string",
                "tooltip": "string",
                "url": "string"
              }
            ],
            "architecture": "string",
            "connection_timeout_seconds": 0,
            "created_at": "2019-08-24T14:15:22Z",
            "directory": "string",
            "disconnected_at": "2019-08-24T14:15:22Z",
            "display_apps": [
              "vscode"
            ],
            "environment_variables": {
              "property1": "string",
              "property2": "string"
            },
            "expanded_directory": "string",
            "first_connected_at": "2019-08-24T14:15:22Z",
            "health": {
              "healthy": false,
              "reason": "agent has lost connection"
            },
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "instance_id": "string",
            "last_connected_at": "2019-08-24T14:15:22Z",
            "latency": {
              "property1": {
                "latency_ms": 0,
                "preferred": true
              },
              "property2": {
                "latency_ms": 0,
                "preferred": true
              }
            },
            "lifecycle_state": "created",
            "log_sources": [
              {
                "created_at": "2019-08-24T14:15:22Z",
                "display_name": "string",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
              }
            ],
            "logs_length": 0,
            "logs_overflowed": true,
            "metadata": [
              {
                "description": {
                  "display_name": "string",
                  "interval": 0,
                  "key": "string",
                  "script": "string",
                  "timeout": 0
                },
                "result": {
                  "age": 0,
                  "collected_at": "2019-08-24T14:15:22Z",
                  "error": "string",
                  "value": "string"
                }
              }
            ],
            "name": "string",
            "operating_system": "string",
            "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
            "ready_at": "2019-08-24T14:15:22Z",
            "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
            "scripts": [
              {
                "cron": "string",
                "display_name": "string",
                "exit_code": 0,
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "log_path": "string",
                "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                "run_on_start": true,
                "run_on_stop": true,
                "script": "string",
                "start_blocks_login": true,
                "status": "ok",
                "timeout": 0
              }
            ],
            "started_at": "2019-08-24T14:15:22Z",
            "startup_script_behavior": "blocking",
            "status": "connecting",
            "subsystems": [
              "envbox"
            ],
            "troubleshooting_url": "string",
            "updated_at": "2019-08-24T14:15:22Z",
            "version": "string"
          }
        ],
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "hide": true,
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
        "metadata": [
          {
            "key": "string",
            "sensitive": true,
            "value": "string"
          }
        ],
        "name": "string",
        "type": "string",
        "workspace_transition": "start"
      }
    ],
    "status": "pending",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_name": "string",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start",
    "updated_at": "2019-08-24T14:15:22Z",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string",
    "workspace_owner_avatar_url": "string",
    "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
    "workspace_owner_name": "string"
  },
  "name": "string",
  "next_start_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "outdated": true,
  "owner_avatar_url": "string",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "shared_with": [
    {
      "actor_type": "group",
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "roles": [
        "admin"
      ]
    }
  ],
  "template_active_version_id": "b0da9c29-67d8-4c87-888c-bafe356f7f3c",
  "template_allow_user_cancel_workspace_jobs": true,
  "template_display_name": "string",
  "template_icon": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_name": "string",
  "template_require_active_version": true,
  "template_use_classic_parameter_flow": true,
  "ttl_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                             |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Workspace](schemas.md#codersdkworkspace) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace metadata by ID

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/workspaces/{workspace} \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/workspaces/{workspace}`

> Body parameter

```json
{
  "name": "string"
}
```

### Parameters

| Name        | In   | Type                                                                         | Required | Description             |
|-------------|------|------------------------------------------------------------------------------|----------|-------------------------|
| `workspace` | path | string(uuid)                                                                 | true     | Workspace ID            |
| `body`      | body | [codersdk.UpdateWorkspaceRequest](schemas.md#codersdkupdateworkspacerequest) | true     | Metadata update request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace ACLs

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/acl \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/acl`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Example responses

> 200 Response

```json
{
  "group": [
    {
      "avatar_url": "http://example.com",
      "display_name": "string",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "members": [
        {
          "avatar_url": "http://example.com",
          "created_at": "2019-08-24T14:15:22Z",
          "email": "user@example.com",
          "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
          "is_service_account": true,
          "last_seen_at": "2019-08-24T14:15:22Z",
          "login_type": "",
          "name": "string",
          "status": "active",
          "theme_preference": "string",
          "updated_at": "2019-08-24T14:15:22Z",
          "username": "string"
        }
      ],
      "name": "string",
      "organization_display_name": "string",
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "organization_name": "string",
      "quota_allowance": 0,
      "role": "admin",
      "source": "user",
      "total_member_count": 0
    }
  ],
  "users": [
    {
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "role": "admin",
      "username": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                   |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceACL](schemas.md#codersdkworkspaceacl) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Completely clears the workspace's user and group ACLs

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/workspaces/{workspace}/acl \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/workspaces/{workspace}/acl`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace ACL

### Code samples

```sh
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/workspaces/{workspace}/acl \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PATCH /api/v2/workspaces/{workspace}/acl`

> Body parameter

```json
{
  "group_roles": {
    "property1": "admin",
    "property2": "admin"
  },
  "user_roles": {
    "property1": "admin",
    "property2": "admin"
  }
}
```

### Parameters

| Name        | In   | Type                                                                 | Required | Description                  |
|-------------|------|----------------------------------------------------------------------|----------|------------------------------|
| `workspace` | path | string(uuid)                                                         | true     | Workspace ID                 |
| `body`      | body | [codersdk.UpdateWorkspaceACL](schemas.md#codersdkupdateworkspaceacl) | true     | Update workspace ACL request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Workspace Agent Connection Watch

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/agent-connection-watch \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/agent-connection-watch`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Example responses

> 101 Response

```json
{
  "agent_update": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "lifecycle": "created"
  },
  "build_update": {
    "job_status": "pending",
    "transition": "start"
  },
  "error": {
    "code": 0,
    "details": "string",
    "message": "string",
    "retryable": true
  }
}
```

### Responses

| Status | Meaning                                                                  | Description         | Schema                                                                           |
|--------|--------------------------------------------------------------------------|---------------------|----------------------------------------------------------------------------------|
| 101    | [Switching Protocols](https://tools.ietf.org/html/rfc7231#section-6.2.2) | Switching Protocols | [workspacesdk.ConnectionWatchEvent](schemas.md#workspacesdkconnectionwatchevent) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace autostart schedule by ID

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/autostart \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/workspaces/{workspace}/autostart`

> Body parameter

```json
{
  "schedule": "string"
}
```

### Parameters

| Name        | In   | Type                                                                                           | Required | Description             |
|-------------|------|------------------------------------------------------------------------------------------------|----------|-------------------------|
| `workspace` | path | string(uuid)                                                                                   | true     | Workspace ID            |
| `body`      | body | [codersdk.UpdateWorkspaceAutostartRequest](schemas.md#codersdkupdateworkspaceautostartrequest) | true     | Schedule update request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace automatic updates by ID

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/autoupdates \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/workspaces/{workspace}/autoupdates`

> Body parameter

```json
{
  "automatic_updates": "always"
}
```

### Parameters

| Name        | In   | Type                                                                                                         | Required | Description               |
|-------------|------|--------------------------------------------------------------------------------------------------------------|----------|---------------------------|
| `workspace` | path | string(uuid)                                                                                                 | true     | Workspace ID              |
| `body`      | body | [codersdk.UpdateWorkspaceAutomaticUpdatesRequest](schemas.md#codersdkupdateworkspaceautomaticupdatesrequest) | true     | Automatic updates request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace dormancy status by id

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/dormant \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/workspaces/{workspace}/dormant`

> Body parameter

```json
{
  "dormant": true
}
```

### Parameters

| Name        | In   | Type                                                                           | Required | Description                        |
|-------------|------|--------------------------------------------------------------------------------|----------|------------------------------------|
| `workspace` | path | string(uuid)                                                                   | true     | Workspace ID                       |
| `body`      | body | [codersdk.UpdateWorkspaceDormancy](schemas.md#codersdkupdateworkspacedormancy) | true     | Make a workspace dormant or active |

### Example responses

> 200 Response

```json
{
  "allow_renames": true,
  "automatic_updates": "always",
  "autostart_schedule": "string",
  "created_at": "2019-08-24T14:15:22Z",
  "deleting_at": "2019-08-24T14:15:22Z",
  "dormant_at": "2019-08-24T14:15:22Z",
  "favorite": true,
  "health": {
    "failing_agents": [
      "497f6eca-6276-4993-bfeb-53cbbbba6f08"
    ],
    "healthy": false
  },
  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  "is_prebuild": true,
  "last_used_at": "2019-08-24T14:15:22Z",
  "latest_app_status": {
    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
    "created_at": "2019-08-24T14:15:22Z",
    "icon": "string",
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "message": "string",
    "needs_user_attention": true,
    "state": "working",
    "uri": "string",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
  },
  "latest_build": {
    "build_number": 0,
    "created_at": "2019-08-24T14:15:22Z",
    "daily_cost": 0,
    "deadline": "2019-08-24T14:15:22Z",
    "has_external_agent": true,
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
    "initiator_name": "string",
    "job": {
      "available_workers": [
        "497f6eca-6276-4993-bfeb-53cbbbba6f08"
      ],
      "canceled_at": "2019-08-24T14:15:22Z",
      "completed_at": "2019-08-24T14:15:22Z",
      "created_at": "2019-08-24T14:15:22Z",
      "error": "string",
      "error_code": "REQUIRED_TEMPLATE_VARIABLES",
      "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
      "input": {
        "error": "string",
        "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
        "workspace_build_id": "badaf2eb-96c5-4050-9f1d-db2d39ca5478"
      },
      "logs_overflowed": true,
      "metadata": {
        "template_display_name": "string",
        "template_icon": "string",
        "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
        "template_name": "string",
        "template_version_name": "string",
        "workspace_build_transition": "start",
        "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
        "workspace_name": "string"
      },
      "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
      "queue_position": 0,
      "queue_size": 0,
      "started_at": "2019-08-24T14:15:22Z",
      "status": "pending",
      "tags": {
        "property1": "string",
        "property2": "string"
      },
      "type": "template_version_import",
      "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b",
      "worker_name": "string"
    },
    "matched_provisioners": {
      "available": 0,
      "count": 0,
      "most_recently_seen": "2019-08-24T14:15:22Z"
    },
    "max_deadline": "2019-08-24T14:15:22Z",
    "reason": "initiator",
    "resources": [
      {
        "agents": [
          {
            "api_version": "string",
            "apps": [
              {
                "command": "string",
                "display_name": "string",
                "external": true,
                "group": "string",
                "health": "disabled",
                "healthcheck": {
                  "interval": 0,
                  "threshold": 0,
                  "url": "string"
                },
                "hidden": true,
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "open_in": "slim-window",
                "sharing_level": "owner",
                "slug": "string",
                "statuses": [
                  {
                    "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
                    "app_id": "affd1d10-9538-4fc8-9e0b-4594a28c1335",
                    "created_at": "2019-08-24T14:15:22Z",
                    "icon": "string",
                    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                    "message": "string",
                    "needs_user_attention": true,
                    "state": "working",
                    "uri": "string",
                    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9"
                  }
                ],
                "subdomain": true,
                "subdomain_name": "string",
                "tooltip": "string",
                "url": "string"
              }
            ],
            "architecture": "string",
            "connection_timeout_seconds": 0,
            "created_at": "2019-08-24T14:15:22Z",
            "directory": "string",
            "disconnected_at": "2019-08-24T14:15:22Z",
            "display_apps": [
              "vscode"
            ],
            "environment_variables": {
              "property1": "string",
              "property2": "string"
            },
            "expanded_directory": "string",
            "first_connected_at": "2019-08-24T14:15:22Z",
            "health": {
              "healthy": false,
              "reason": "agent has lost connection"
            },
            "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
            "instance_id": "string",
            "last_connected_at": "2019-08-24T14:15:22Z",
            "latency": {
              "property1": {
                "latency_ms": 0,
                "preferred": true
              },
              "property2": {
                "latency_ms": 0,
                "preferred": true
              }
            },
            "lifecycle_state": "created",
            "log_sources": [
              {
                "created_at": "2019-08-24T14:15:22Z",
                "display_name": "string",
                "icon": "string",
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "workspace_agent_id": "7ad2e618-fea7-4c1a-b70a-f501566a72f1"
              }
            ],
            "logs_length": 0,
            "logs_overflowed": true,
            "metadata": [
              {
                "description": {
                  "display_name": "string",
                  "interval": 0,
                  "key": "string",
                  "script": "string",
                  "timeout": 0
                },
                "result": {
                  "age": 0,
                  "collected_at": "2019-08-24T14:15:22Z",
                  "error": "string",
                  "value": "string"
                }
              }
            ],
            "name": "string",
            "operating_system": "string",
            "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
            "ready_at": "2019-08-24T14:15:22Z",
            "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
            "scripts": [
              {
                "cron": "string",
                "display_name": "string",
                "exit_code": 0,
                "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
                "log_path": "string",
                "log_source_id": "4197ab25-95cf-4b91-9c78-f7f2af5d353a",
                "run_on_start": true,
                "run_on_stop": true,
                "script": "string",
                "start_blocks_login": true,
                "status": "ok",
                "timeout": 0
              }
            ],
            "started_at": "2019-08-24T14:15:22Z",
            "startup_script_behavior": "blocking",
            "status": "connecting",
            "subsystems": [
              "envbox"
            ],
            "troubleshooting_url": "string",
            "updated_at": "2019-08-24T14:15:22Z",
            "version": "string"
          }
        ],
        "created_at": "2019-08-24T14:15:22Z",
        "daily_cost": 0,
        "hide": true,
        "icon": "string",
        "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
        "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
        "metadata": [
          {
            "key": "string",
            "sensitive": true,
            "value": "string"
          }
        ],
        "name": "string",
        "type": "string",
        "workspace_transition": "start"
      }
    ],
    "status": "pending",
    "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
    "template_version_name": "string",
    "template_version_preset_id": "512a53a7-30da-446e-a1fc-713c630baff1",
    "transition": "start",
    "updated_at": "2019-08-24T14:15:22Z",
    "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
    "workspace_name": "string",
    "workspace_owner_avatar_url": "string",
    "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
    "workspace_owner_name": "string"
  },
  "name": "string",
  "next_start_at": "2019-08-24T14:15:22Z",
  "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6",
  "organization_name": "string",
  "outdated": true,
  "owner_avatar_url": "string",
  "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  "owner_name": "string",
  "shared_with": [
    {
      "actor_type": "group",
      "avatar_url": "http://example.com",
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "name": "string",
      "roles": [
        "admin"
      ]
    }
  ],
  "template_active_version_id": "b0da9c29-67d8-4c87-888c-bafe356f7f3c",
  "template_allow_user_cancel_workspace_jobs": true,
  "template_display_name": "string",
  "template_icon": "string",
  "template_id": "c6d67e98-83ea-49f0-8812-e4abae2b68bc",
  "template_name": "string",
  "template_require_active_version": true,
  "template_use_classic_parameter_flow": true,
  "ttl_ms": 0,
  "updated_at": "2019-08-24T14:15:22Z"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                             |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Workspace](schemas.md#codersdkworkspace) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Extend workspace deadline by ID

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/extend \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/workspaces/{workspace}/extend`

> Body parameter

```json
{
  "deadline": "2019-08-24T14:15:22Z"
}
```

### Parameters

| Name        | In   | Type                                                                               | Required | Description                    |
|-------------|------|------------------------------------------------------------------------------------|----------|--------------------------------|
| `workspace` | path | string(uuid)                                                                       | true     | Workspace ID                   |
| `body`      | body | [codersdk.PutExtendWorkspaceRequest](schemas.md#codersdkputextendworkspacerequest) | true     | Extend deadline update request |

### Example responses

> 200 Response

```json
{
  "detail": "string",
  "message": "string",
  "validations": [
    {
      "detail": "string",
      "field": "string"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Favorite workspace by ID

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/favorite \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/workspaces/{workspace}/favorite`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Unfavorite workspace by ID

### Code samples

```sh
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/workspaces/{workspace}/favorite \
  -H 'Coder-Session-Token: API_KEY'
```

`DELETE /api/v2/workspaces/{workspace}/favorite`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Resolve workspace autostart by id

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/resolve-autostart \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/resolve-autostart`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Example responses

> 200 Response

```json
{
  "parameter_mismatch": true
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                           |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ResolveAutostartResponse](schemas.md#codersdkresolveautostartresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Get workspace timings by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/timings \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/timings`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Example responses

> 200 Response

```json
{
  "agent_connection_timings": [
    {
      "ended_at": "2019-08-24T14:15:22Z",
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z",
      "workspace_agent_id": "string",
      "workspace_agent_name": "string"
    }
  ],
  "agent_script_timings": [
    {
      "display_name": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "exit_code": 0,
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z",
      "status": "string",
      "workspace_agent_id": "string",
      "workspace_agent_name": "string"
    }
  ],
  "provisioner_timings": [
    {
      "action": "string",
      "ended_at": "2019-08-24T14:15:22Z",
      "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
      "resource": "string",
      "source": "string",
      "stage": "init",
      "started_at": "2019-08-24T14:15:22Z"
    }
  ]
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                                     |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.WorkspaceBuildTimings](schemas.md#codersdkworkspacebuildtimings) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Update workspace TTL by ID

### Code samples

```sh
# Example request using curl
curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/ttl \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`PUT /api/v2/workspaces/{workspace}/ttl`

> Body parameter

```json
{
  "ttl_ms": 0
}
```

### Parameters

| Name        | In   | Type                                                                               | Required | Description                  |
|-------------|------|------------------------------------------------------------------------------------|----------|------------------------------|
| `workspace` | path | string(uuid)                                                                       | true     | Workspace ID                 |
| `body`      | body | [codersdk.UpdateWorkspaceTTLRequest](schemas.md#codersdkupdateworkspacettlrequest) | true     | Workspace TTL update request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Post Workspace Usage by ID

### Code samples

```sh
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/usage \
  -H 'Content-Type: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`POST /api/v2/workspaces/{workspace}/usage`

> Body parameter

```json
{
  "agent_id": "2b1e3b65-2c04-4fa2-a2d7-467901e98978",
  "app_name": "string"
}
```

### Parameters

| Name        | In   | Type                                                                               | Required | Description                  |
|-------------|------|------------------------------------------------------------------------------------|----------|------------------------------|
| `workspace` | path | string(uuid)                                                                       | true     | Workspace ID                 |
| `body`      | body | [codersdk.PostWorkspaceUsageRequest](schemas.md#codersdkpostworkspaceusagerequest) | false    | Post workspace usage request |

### Responses

| Status | Meaning                                                         | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204    | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content  |        |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Watch workspace by ID

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/watch \
  -H 'Accept: text/event-stream' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/watch`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Example responses

> 200 Response

### Responses

| Status | Meaning                                                 | Description | Schema                                           |
|--------|---------------------------------------------------------|-------------|--------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.Response](schemas.md#codersdkresponse) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

## Watch workspace by ID via WebSockets

### Code samples

```sh
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/watch-ws \
  -H 'Accept: application/json' \
  -H 'Coder-Session-Token: API_KEY'
```

`GET /api/v2/workspaces/{workspace}/watch-ws`

### Parameters

| Name        | In   | Type         | Required | Description  |
|-------------|------|--------------|----------|--------------|
| `workspace` | path | string(uuid) | true     | Workspace ID |

### Example responses

> 200 Response

```json
{
  "data": null,
  "type": "ping"
}
```

### Responses

| Status | Meaning                                                 | Description | Schema                                                         |
|--------|---------------------------------------------------------|-------------|----------------------------------------------------------------|
| 200    | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK          | [codersdk.ServerSentEvent](schemas.md#codersdkserversentevent) |

To perform this operation, you must be authenticated. [Learn more](authentication.md).

---

# Command Line

Source: https://coder.com/docs/reference/cli

<!-- DO NOT EDIT | GENERATED CONTENT -->

## Usage

```console
coder [global-flags] <subcommand>
```

## Description

```console
Coder — A tool for provisioning self-hosted development environments with Terraform.
  - Start a Coder server:

     $ coder server

  - Get started by creating a template from an example:

     $ coder templates init
```

## Subcommands

| Name                                                               | Purpose                                                                                                                      |
|--------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
| [<code>completion</code>](./completion.md)                         | Install or update shell completion scripts for the detected or chosen shell.                                                 |
| [<code>dotfiles</code>](./dotfiles.md)                             | Personalize your workspace by applying a canonical dotfiles repository                                                       |
| [<code>external-auth</code>](./external-auth/index.md)             | Manage external authentication                                                                                               |
| [<code>login</code>](./login/index.md)                             | Authenticate with Coder deployment                                                                                           |
| [<code>logout</code>](./logout.md)                                 | Unauthenticate your local session                                                                                            |
| [<code>netcheck</code>](./netcheck.md)                             | Print network debug information for DERP and STUN                                                                            |
| [<code>notifications</code>](./notifications/index.md)             | Manage Coder notifications                                                                                                   |
| [<code>oauth2-provider</code>](./oauth2-provider/index.md)         | Manage Coder OAuth2 provider settings                                                                                        |
| [<code>organizations</code>](./organizations/index.md)             | Organization related commands                                                                                                |
| [<code>port-forward</code>](./port-forward.md)                     | Forward ports from a workspace to the local machine. For reverse port forwarding, use "coder ssh -R".                        |
| [<code>publickey</code>](./publickey.md)                           | Output your Coder public key used for Git operations                                                                         |
| [<code>reset-password</code>](./reset-password.md)                 | Directly connect to the database to reset a user's password                                                                  |
| [<code>secret</code>](./secret/index.md)                           | Manage secrets                                                                                                               |
| [<code>state</code>](./state/index.md)                             | Manually manage Terraform state to fix broken workspaces                                                                     |
| [<code>templates</code>](./templates/index.md)                     | Manage templates                                                                                                             |
| [<code>tokens</code>](./tokens/index.md)                           | Manage personal access tokens                                                                                                |
| [<code>users</code>](./users/index.md)                             | Manage users                                                                                                                 |
| [<code>version</code>](./version.md)                               | Show coder version                                                                                                           |
| [<code>autoupdate</code>](./autoupdate.md)                         | Toggle auto-update policy for a workspace                                                                                    |
| [<code>config-ssh</code>](./config-ssh.md)                         | Add an SSH Host entry for your workspaces "ssh workspace.coder"                                                              |
| [<code>create</code>](./create.md)                                 | Create a workspace                                                                                                           |
| [<code>delete</code>](./delete.md)                                 | Delete a workspace                                                                                                           |
| [<code>favorite</code>](./favorite.md)                             | Add a workspace to your favorites                                                                                            |
| [<code>list</code>](./list.md)                                     | List workspaces                                                                                                              |
| [<code>logs</code>](./logs.md)                                     | View logs for a workspace                                                                                                    |
| [<code>open</code>](./open/index.md)                               | Open a workspace                                                                                                             |
| [<code>ping</code>](./ping.md)                                     | Ping a workspace                                                                                                             |
| [<code>rename</code>](./rename.md)                                 | Rename a workspace                                                                                                           |
| [<code>restart</code>](./restart.md)                               | Restart a workspace                                                                                                          |
| [<code>schedule</code>](./schedule/index.md)                       | Schedule automated start and stop times for workspaces                                                                       |
| [<code>show</code>](./show.md)                                     | Display details of a workspace's resources and agents                                                                        |
| [<code>speedtest</code>](./speedtest.md)                           | Run upload and download tests from your machine to a workspace                                                               |
| [<code>ssh</code>](./ssh.md)                                       | Start a shell into a workspace or run a command                                                                              |
| [<code>start</code>](./start.md)                                   | Start a workspace                                                                                                            |
| [<code>stat</code>](./stat/index.md)                               | Show resource usage for the current workspace.                                                                               |
| [<code>stop</code>](./stop.md)                                     | Stop a workspace                                                                                                             |
| [<code>unfavorite</code>](./unfavorite.md)                         | Remove a workspace from your favorites                                                                                       |
| [<code>update</code>](./update.md)                                 | Will update and start a given workspace if it is out of date. If the workspace is already running, it will be stopped first. |
| [<code>whoami</code>](./whoami.md)                                 | Fetch authenticated user info for Coder deployment                                                                           |
| [<code>support</code>](./support/index.md)                         | Commands for troubleshooting issues with a Coder deployment.                                                                 |
| [<code>server</code>](./server/index.md)                           | Start a Coder server                                                                                                         |
| [<code>provisioner</code>](./provisioner/index.md)                 | View and manage provisioner daemons and jobs                                                                                 |
| [<code>ai-gateway</code>](./ai-gateway/index.md)                   | Manage AI Gateway                                                                                                            |
| [<code>agent-firewall</code>](./agent-firewall.md)                 | Network isolation tool for monitoring and restricting HTTP/HTTPS requests                                                    |
| [<code>features</code>](./features/index.md)                       | List Enterprise features                                                                                                     |
| [<code>licenses</code>](./licenses/index.md)                       | Add, delete, and list licenses                                                                                               |
| [<code>groups</code>](./groups/index.md)                           | Manage groups                                                                                                                |
| [<code>prebuilds</code>](./prebuilds/index.md)                     | Manage Coder prebuilds                                                                                                       |
| [<code>external-workspaces</code>](./external-workspaces/index.md) | Create or manage external workspaces                                                                                         |

## Options

### --url

|             |                         |
|-------------|-------------------------|
| Type        | <code>url</code>        |
| Environment | <code>$CODER_URL</code> |

URL to a deployment.

### --debug-options

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Print all options, how they're set, then exit.

### --token

|             |                                   |
|-------------|-----------------------------------|
| Type        | <code>string</code>               |
| Environment | <code>$CODER_SESSION_TOKEN</code> |

Specify an authentication token. For security reasons setting CODER_SESSION_TOKEN is preferred.

### --no-version-warning

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>bool</code>                      |
| Environment | <code>$CODER_NO_VERSION_WARNING</code> |

Suppress warning when client and server versions do not match.

### --no-feature-warning

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>bool</code>                      |
| Environment | <code>$CODER_NO_FEATURE_WARNING</code> |

Suppress warnings about unlicensed features.

### --allow-redirects

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>bool</code>                   |
| Environment | <code>$CODER_ALLOW_REDIRECTS</code> |

Follow HTTP redirects from the server instead of returning an error. Following redirects may alter the request method and/or drop its body.

### --header

|             |                            |
|-------------|----------------------------|
| Type        | <code>string-array</code>  |
| Environment | <code>$CODER_HEADER</code> |

Additional HTTP headers added to all requests. Provide as key=value. Can be specified multiple times.

### --header-command

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>string</code>                |
| Environment | <code>$CODER_HEADER_COMMAND</code> |

An external command that outputs additional HTTP headers added to all requests. The command must output each header as `key=value` on its own line. If a header value is a JWT, it will be refreshed based on the value in its `exp` field.

### --force-tty

|             |                               |
|-------------|-------------------------------|
| Type        | <code>bool</code>             |
| Environment | <code>$CODER_FORCE_TTY</code> |

Force the use of a TTY.

### -v, --verbose

|             |                             |
|-------------|-----------------------------|
| Type        | <code>bool</code>           |
| Environment | <code>$CODER_VERBOSE</code> |

Enable verbose output.

### --flight-recorder-size

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>int</code>                         |
| Environment | <code>$CODER_FLIGHT_RECORDER_SIZE</code> |
| Default     | <code>10</code>                          |

Number of log entries below the current log level to keep in memory and emit on errors. Set to 0 to disable the flight recorder.

### --disable-direct-connections

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>bool</code>                              |
| Environment | <code>$CODER_DISABLE_DIRECT_CONNECTIONS</code> |

Disable direct (P2P) connections to workspaces.

### --disable-network-telemetry

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>bool</code>                             |
| Environment | <code>$CODER_DISABLE_NETWORK_TELEMETRY</code> |

Disable network telemetry. Network telemetry is collected when connecting to workspaces using the CLI, and is forwarded to the server. If telemetry is also enabled on the server, it may be sent to Coder. Network telemetry is used to measure network quality and detect regressions.

### --client-tls-ca-file

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string</code>                    |
| Environment | <code>$CODER_CLIENT_TLS_CA_FILE</code> |

Path to a CA certificate file to trust for API and DERP connections.

### --client-tls-cert-file

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_CLIENT_TLS_CERT_FILE</code> |

Path to a client certificate file for mTLS authentication with API and DERP. Requires --client-tls-key-file.

### --client-tls-key-file

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_CLIENT_TLS_KEY_FILE</code> |

Path to a client private key file for mTLS authentication with API and DERP. Requires --client-tls-cert-file.

### --use-keyring

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>bool</code>               |
| Environment | <code>$CODER_USE_KEYRING</code> |
| Default     | <code>true</code>               |

Store and retrieve session tokens using the operating system keyring. This flag is ignored and file-based storage is used when --global-config is set or keyring usage is not supported on the current platform. Set to false to force file-based storage on supported platforms.

### --global-config

|             |                                |
|-------------|--------------------------------|
| Type        | <code>string</code>            |
| Environment | <code>$CODER_CONFIG_DIR</code> |
| Default     | <code>~/.config/coderv2</code> |

Path to the global `coder` config directory.

---

# coder agent-firewall

Source: https://coder.com/docs/reference/cli/agent-firewall

<!-- DO NOT EDIT | GENERATED CONTENT -->

Network isolation tool for monitoring and restricting HTTP/HTTPS requests

## Usage

```console
coder agent-firewall [flags] [args...]
```

## Description

```console
boundary creates an isolated network environment for target processes, intercepting HTTP/HTTPS traffic through a transparent proxy that enforces user-defined allow rules.
```

## Options

### --config

|             |                               |
|-------------|-------------------------------|
| Type        | <code>yaml-config-path</code> |
| Environment | <code>$BOUNDARY_CONFIG</code> |

Path to YAML config file.

### --allow

|             |                              |
|-------------|------------------------------|
| Type        | <code>string</code>          |
| Environment | <code>$BOUNDARY_ALLOW</code> |

Allow rule (repeatable). These are merged with allowlist from config file. Format: "pattern" or "METHOD[,METHOD] pattern".

### --log-level

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$BOUNDARY_LOG_LEVEL</code> |
| YAML        | <code>log_level</code>           |
| Default     | <code>warn</code>                |

Set log level (error, warn, info, debug).

### --log-dir

|             |                                |
|-------------|--------------------------------|
| Type        | <code>string</code>            |
| Environment | <code>$BOUNDARY_LOG_DIR</code> |
| YAML        | <code>log_dir</code>           |

Set a directory to write logs to rather than stderr.

### --proxy-port

|             |                          |
|-------------|--------------------------|
| Type        | <code>int</code>         |
| Environment | <code>$PROXY_PORT</code> |
| YAML        | <code>proxy_port</code>  |
| Default     | <code>8080</code>        |

Set a port for HTTP proxy.

### --pprof

|             |                              |
|-------------|------------------------------|
| Type        | <code>bool</code>            |
| Environment | <code>$BOUNDARY_PPROF</code> |
| YAML        | <code>pprof_enabled</code>   |

Enable pprof profiling server.

### --pprof-port

|             |                                   |
|-------------|-----------------------------------|
| Type        | <code>int</code>                  |
| Environment | <code>$BOUNDARY_PPROF_PORT</code> |
| YAML        | <code>pprof_port</code>           |
| Default     | <code>6060</code>                 |

Set port for pprof profiling server.

### --jail-type

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$BOUNDARY_JAIL_TYPE</code> |
| YAML        | <code>jail_type</code>           |
| Default     | <code>nsjail</code>              |

Jail type to use for network isolation. Options: nsjail (default), landjail.

### --use-real-dns

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>bool</code>                   |
| Environment | <code>$BOUNDARY_USE_REAL_DNS</code> |
| YAML        | <code>use_real_dns</code>           |

Use real DNS in the jail instead of the dummy DNS (allows DNS exfiltration). Default: false.

### --no-user-namespace

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>bool</code>                        |
| Environment | <code>$BOUNDARY_NO_USER_NAMESPACE</code> |
| YAML        | <code>no_user_namespace</code>           |

Do not create a user namespace. Use in restricted environments that disallow user NS (e.g. Bottlerocket in EKS auto-mode).

### --disable-audit-logs

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>bool</code>                |
| Environment | <code>$DISABLE_AUDIT_LOGS</code> |
| YAML        | <code>disable_audit_logs</code>  |

Disable sending of audit logs to the workspace agent when set to true.

### --log-proxy-socket-path

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>string</code>                                      |
| Environment | <code>$CODER_AGENT_BOUNDARY_LOG_PROXY_SOCKET_PATH</code> |
| Default     | <code>/tmp/boundary-audit.sock</code>                    |

Path to the socket where the boundary log proxy server listens for audit logs.

### --version

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Print version information and exit.

### --enable-session-correlation

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>bool</code>                                  |
| Environment | <code>$BOUNDARY_SESSION_CORRELATION_ENABLED</code> |
| YAML        | <code>session_correlation_enabled</code>           |

Enable session correlation header injection. When no inject targets are configured, the target is auto-derived from CODER_AGENT_URL (set automatically inside Coder workspaces). Disable for deployments without Coder AI Gateway in front.

### --session-id-inject-target

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>string</code>                             |
| Environment | <code>$BOUNDARY_SESSION_ID_INJECT_TARGET</code> |

Inject target for session correlation headers. Repeat the flag once per target; each value describes exactly one target. Format: `domain=<host> [path=<glob>]`. Example: `--session-id-inject-target "domain=prod.coder.com path=/api/v2/aibridge/*"`.

---

# coder ai-gateway

Source: https://coder.com/docs/reference/cli/ai-gateway

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage AI Gateway

## Usage

```console
coder ai-gateway
```

## Subcommands

| Name                                 | Purpose                            |
|--------------------------------------|------------------------------------|
| [<code>start</code>](./start.md)     | Run a standalone AI Gateway server |
| [<code>keys</code>](./keys/index.md) | Manage AI Gateway keys             |

---

# coder ai-gateway keys

Source: https://coder.com/docs/reference/cli/ai-gateway/keys

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage AI Gateway keys

## Usage

```console
coder ai-gateway keys
```

## Subcommands

| Name                               | Purpose                  |
|------------------------------------|--------------------------|
| [<code>create</code>](./create.md) | Create an AI Gateway key |
| [<code>delete</code>](./delete.md) | Delete an AI Gateway key |
| [<code>list</code>](./list.md)     | List AI Gateway keys     |

---

# coder ai-gateway keys create

Source: https://coder.com/docs/reference/cli/ai-gateway/keys/create

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create an AI Gateway key

## Usage

```console
coder ai-gateway keys create <name>
```

---

# coder ai-gateway keys delete

Source: https://coder.com/docs/reference/cli/ai-gateway/keys/delete

<!-- DO NOT EDIT | GENERATED CONTENT -->

Delete an AI Gateway key

Aliases:

* rm

## Usage

```console
coder ai-gateway keys delete [flags] <name|id>
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder ai-gateway keys list

Source: https://coder.com/docs/reference/cli/ai-gateway/keys/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List AI Gateway keys

Aliases:

* ls

## Usage

```console
coder ai-gateway keys list [flags]
```

## Options

### -c, --column

|         |                                                                    |
|---------|--------------------------------------------------------------------|
| Type    | <code>[id\|name\|key prefix\|created at\|last heartbeat at]</code> |
| Default | <code>id,name,key prefix,last heartbeat at,created at</code>       |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder ai-gateway start

Source: https://coder.com/docs/reference/cli/ai-gateway/start

<!-- DO NOT EDIT | GENERATED CONTENT -->

Run a standalone AI Gateway server

## Usage

```console
coder ai-gateway start [flags]
```

## Description

```console
Runs a standalone replica of the AI Gateway. Standalone replicas serve LLM client traffic on a dedicated HTTP listener and connect to coderd using the Coder deployment URL and an AI Gateway key.

Set --url or CODER_URL to the Coder deployment address, and set --key (CODER_AI_GATEWAY_KEY) or --key-file (CODER_AI_GATEWAY_KEY_FILE). A user login or session token is not required.
```

## Options

### --key

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>string</code>                |
| Environment | <code>$CODER_AI_GATEWAY_KEY</code> |

The AI Gateway key used to authenticate to coderd.

### --key-file

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_AI_GATEWAY_KEY_FILE</code> |

Path to a file containing the AI Gateway key used to authenticate to coderd.

### --http-address

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_AI_GATEWAY_HTTP_ADDRESS</code> |
| Default     | <code>127.0.0.1:4001</code>                 |

The bind address to serve incoming AI Gateway client traffic.

### --tls-cert-file

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>string</code>                          |
| Environment | <code>$CODER_AI_GATEWAY_TLS_CERT_FILE</code> |

Path to a PEM-encoded TLS certificate. Enables TLS termination when set together with --tls-key-file.

### --tls-key-file

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_AI_GATEWAY_TLS_KEY_FILE</code> |

Path to a PEM-encoded TLS private key. Enables TLS termination when set together with --tls-cert-file.

### --prometheus-enable

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>bool</code>                            |
| Environment | <code>$CODER_PROMETHEUS_ENABLE</code>        |
| YAML        | <code>introspection.prometheus.enable</code> |

Serve prometheus metrics on the address defined by prometheus address.

### --prometheus-address

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>host:port</code>                        |
| Environment | <code>$CODER_PROMETHEUS_ADDRESS</code>        |
| YAML        | <code>introspection.prometheus.address</code> |
| Default     | <code>127.0.0.1:2112</code>                   |

The bind address to serve prometheus metrics.

### --trace

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>bool</code>                         |
| Environment | <code>$CODER_TRACE_ENABLE</code>          |
| YAML        | <code>introspection.tracing.enable</code> |

Whether application tracing data is collected. It exports to a backend configured by environment variables. See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md.

### --trace-honeycomb-api-key

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_TRACE_HONEYCOMB_API_KEY</code> |

Enables trace exporting to Honeycomb.io using the provided API Key.

### --trace-logs

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>bool</code>                              |
| Environment | <code>$CODER_TRACE_LOGS</code>                 |
| YAML        | <code>introspection.tracing.captureLogs</code> |

Enables capturing of logs as events in traces. This is useful for debugging, but may result in a very large amount of events being sent to the tracing backend which may incur significant costs.

### -l, --log-filter

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>string-array</code>                 |
| Environment | <code>$CODER_LOG_FILTER</code>            |
| YAML        | <code>introspection.logging.filter</code> |

Filter debug logs by matching against a given regex. Use .* to match all debug logs.

### --log-human

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>string</code>                          |
| Environment | <code>$CODER_LOGGING_HUMAN</code>            |
| YAML        | <code>introspection.logging.humanPath</code> |
| Default     | <code>/dev/stderr</code>                     |

Output human-readable logs to a given file.

### --log-json

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_LOGGING_JSON</code>            |
| YAML        | <code>introspection.logging.jsonPath</code> |

Output JSON logs to a given file.

### --log-stackdriver

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>string</code>                                |
| Environment | <code>$CODER_LOGGING_STACKDRIVER</code>            |
| YAML        | <code>introspection.logging.stackdriverPath</code> |

Output Stackdriver compatible logs to a given file.

### --experiments

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>string-array</code>       |
| Environment | <code>$CODER_EXPERIMENTS</code> |
| YAML        | <code>experiments</code>        |

Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.

### -c, --config

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>yaml-config-path</code>   |
| Environment | <code>$CODER_CONFIG_PATH</code> |

Specify a YAML file to load configuration from.

### --ai-gateway-max-concurrency

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>int</code>                               |
| Environment | <code>$CODER_AI_GATEWAY_MAX_CONCURRENCY</code> |
| YAML        | <code>ai_gateway.max_concurrency</code>        |
| Default     | <code>0</code>                                 |

Maximum number of concurrent AI Gateway requests per replica. Set to 0 to disable (unlimited).

### --ai-gateway-rate-limit

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>int</code>                          |
| Environment | <code>$CODER_AI_GATEWAY_RATE_LIMIT</code> |
| YAML        | <code>ai_gateway.rate_limit</code>        |
| Default     | <code>0</code>                            |

Maximum number of AI Gateway requests per second per replica. Set to 0 to disable (unlimited).

### --ai-gateway-structured-logging

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>bool</code>                                 |
| Environment | <code>$CODER_AI_GATEWAY_STRUCTURED_LOGGING</code> |
| YAML        | <code>ai_gateway.structured_logging</code>        |
| Default     | <code>false</code>                                |

Emit structured logs for AI Gateway interception records. Use this for exporting these records to external SIEM or observability systems.

### --ai-gateway-structured-logging-source

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>coderd\|gateway\|both</code>                       |
| Environment | <code>$CODER_AI_GATEWAY_STRUCTURED_LOGGING_SOURCE</code> |
| YAML        | <code>ai_gateway.structured_logging_source</code>        |
| Default     | <code>coderd</code>                                      |

Which process emits AI Gateway interception records when structured logging is enabled: coderd, the gateway, or both. The gateway emits records that are never persisted, such as those dropped by --ai-gateway-disable-content-recording, but cannot report thread_parent_id or thread_root_id. Use both to verify a move from one to the other; records reaching coderd are then reported twice. A standalone gateway must be configured to emit its own records, and its logs shipped rather than coderd's.

### --ai-gateway-disable-content-recording

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>bool</code>                                        |
| Environment | <code>$CODER_AI_GATEWAY_DISABLE_CONTENT_RECORDING</code> |
| YAML        | <code>ai_gateway.disable_content_recording</code>        |
| Default     | <code>false</code>                                       |

Stop recording the content of intercepted conversations. No user prompt, tool call or model reasoning record is stored, including tool names and the arguments they were called with. Interceptions and token usage are still recorded, so cost controls, budget enforcement and spend reporting are unaffected. Sessions show no conversation detail, prompt and tool call telemetry report zero, and interceptions are no longer grouped into threads for clients that do not send their own session ID. Combine with --ai-gateway-structured-logging-source=gateway to keep exporting these records to a SIEM instead.

### --ai-gateway-send-actor-headers

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>bool</code>                                 |
| Environment | <code>$CODER_AI_GATEWAY_SEND_ACTOR_HEADERS</code> |
| YAML        | <code>ai_gateway.send_actor_headers</code>        |
| Default     | <code>false</code>                                |

Add configured headers identifying the authenticated user to intercepted upstream requests. Use this when a proxy between AI Gateway and an upstream AI provider needs user identity. When enabled, removes client-supplied headers at configured actor-header destinations before adding authenticated values. Client headers starting with X-AI-Bridge-Actor are always removed.

### --ai-gateway-actor-header-id

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>string</code>                            |
| Environment | <code>$CODER_AI_GATEWAY_ACTOR_HEADER_ID</code> |
| YAML        | <code>ai_gateway.actor_header_id</code>        |
| Default     | <code>X-AI-Bridge-Actor-ID</code>              |

Header name for the authenticated user's ID. Empty disables this header. Requires AI Gateway actor headers to be enabled.

### --ai-gateway-actor-header-username

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>string</code>                                  |
| Environment | <code>$CODER_AI_GATEWAY_ACTOR_HEADER_USERNAME</code> |
| YAML        | <code>ai_gateway.actor_header_username</code>        |
| Default     | <code>X-AI-Bridge-Actor-Metadata-Username</code>     |

Header name for the authenticated user's username. Empty disables this header. Requires AI Gateway actor headers to be enabled.

### --ai-gateway-actor-header-email

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>string</code>                               |
| Environment | <code>$CODER_AI_GATEWAY_ACTOR_HEADER_EMAIL</code> |
| YAML        | <code>ai_gateway.actor_header_email</code>        |

Header name for the authenticated user's email address. Empty disables this header. Requires AI Gateway actor headers to be enabled. Applies to every configured provider; email is personal information.

### --ai-gateway-dump-dir

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_AI_GATEWAY_DUMP_DIR</code> |
| YAML        | <code>ai_gateway.api_dump_dir</code>    |

Base directory for dumping AI Gateway request/response pairs to disk for debugging. When set, each provider writes under a subdirectory named after the provider. Sensitive headers are redacted. Leave empty to disable.

### --ai-gateway-allow-byok

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>bool</code>                         |
| Environment | <code>$CODER_AI_GATEWAY_ALLOW_BYOK</code> |
| YAML        | <code>ai_gateway.allow_byok</code>        |
| Default     | <code>true</code>                         |

Allow users to provide their own LLM API keys or subscriptions. When disabled, only centralized key authentication is permitted.

### --ai-gateway-circuit-breaker-enabled

|             |                                                        |
|-------------|--------------------------------------------------------|
| Type        | <code>bool</code>                                      |
| Environment | <code>$CODER_AI_GATEWAY_CIRCUIT_BREAKER_ENABLED</code> |
| YAML        | <code>ai_gateway.circuit_breaker_enabled</code>        |
| Default     | <code>false</code>                                     |

Enable the circuit breaker to protect against cascading failures from upstream AI provider overload (503, 529).

---

# coder autoupdate

Source: https://coder.com/docs/reference/cli/autoupdate

<!-- DO NOT EDIT | GENERATED CONTENT -->

Toggle auto-update policy for a workspace

## Usage

```console
coder autoupdate [flags] <workspace> <always|never>
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder completion

Source: https://coder.com/docs/reference/cli/completion

<!-- DO NOT EDIT | GENERATED CONTENT -->

Install or update shell completion scripts for the detected or chosen shell.

## Usage

```console
coder completion [flags]
```

## Options

### -s, --shell

|      |                                          |
|------|------------------------------------------|
| Type | <code>bash\|fish\|zsh\|powershell</code> |

The shell to install completion for.

### -p, --print

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Print the completion script instead of installing it.

---

# coder config-ssh

Source: https://coder.com/docs/reference/cli/config-ssh

<!-- DO NOT EDIT | GENERATED CONTENT -->

Add an SSH Host entry for your workspaces "ssh workspace.coder"

## Usage

```console
coder config-ssh [flags]
```

## Description

```console
  - You can use -o (or --ssh-option) so set SSH options to be used for all your
workspaces:

     $ coder config-ssh -o ForwardAgent=yes

  - You can use --dry-run (or -n) to see the changes that would be made:

     $ coder config-ssh --dry-run
```

## Options

### --ssh-config-file

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string</code>                 |
| Environment | <code>$CODER_SSH_CONFIG_FILE</code> |
| Default     | <code>~/.ssh/config</code>          |

Specifies the path to an SSH config.

### --coder-binary-path

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string</code>                        |
| Environment | <code>$CODER_SSH_CONFIG_BINARY_PATH</code> |

Optionally specify the absolute path to the coder binary used in ProxyCommand. By default, the binary invoking this command ('config ssh') is used.

### -o, --ssh-option

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string-array</code>           |
| Environment | <code>$CODER_SSH_CONFIG_OPTS</code> |

Specifies additional SSH options to embed in each host stanza.

### -n, --dry-run

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>bool</code>               |
| Environment | <code>$CODER_SSH_DRY_RUN</code> |

Perform a trial run with no changes made, showing a diff at the end.

### --use-previous-options

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>bool</code>                            |
| Environment | <code>$CODER_SSH_USE_PREVIOUS_OPTIONS</code> |

Specifies whether or not to keep options from previous run of config-ssh.

### --ssh-host-prefix

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>string</code>                           |
| Environment | <code>$CODER_CONFIGSSH_SSH_HOST_PREFIX</code> |

Override the default host prefix.

### --hostname-suffix

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>string</code>                           |
| Environment | <code>$CODER_CONFIGSSH_HOSTNAME_SUFFIX</code> |

Override the default hostname suffix.

### --wait

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>yes\|no\|auto</code>         |
| Environment | <code>$CODER_CONFIGSSH_WAIT</code> |
| Default     | <code>auto</code>                  |

Specifies whether or not to wait for the startup script to finish executing. Auto means that the agent startup script behavior configured in the workspace template is used.

### --disable-autostart

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>bool</code>                               |
| Environment | <code>$CODER_CONFIGSSH_DISABLE_AUTOSTART</code> |
| Default     | <code>false</code>                              |

Disable starting the workspace automatically when connecting via SSH.

### --no-wildcard

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>bool</code>                         |
| Environment | <code>$CODER_CONFIGSSH_NO_WILDCARD</code> |
| Default     | <code>false</code>                        |

Generate an individual host entry for each workspace instead of a wildcard host block. This allows third-party tools and SSH clients to discover workspaces by reading the config file.

### --force-unix-filepaths

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>bool</code>                            |
| Environment | <code>$CODER_CONFIGSSH_UNIX_FILEPATHS</code> |

By default, 'config-ssh' uses the os path separator when writing the ssh config. This might be an issue in Windows machine that use a unix-like shell. This flag forces the use of unix file paths (the forward slash '/').

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder create

Source: https://coder.com/docs/reference/cli/create

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create a workspace

## Usage

```console
coder create [flags] [workspace]
```

## Description

```console
  - Create a workspace for another user (if you have permission):

     $ coder create <username>/<workspace_name>
```

## Options

### -t, --template

|             |                                   |
|-------------|-----------------------------------|
| Type        | <code>string</code>               |
| Environment | <code>$CODER_TEMPLATE_NAME</code> |

Specify a template name.

### --template-version

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string</code>                  |
| Environment | <code>$CODER_TEMPLATE_VERSION</code> |

Specify a template version name.

### --preset

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>string</code>             |
| Environment | <code>$CODER_PRESET_NAME</code> |

Specify the name of a template version preset. Use 'none' to explicitly indicate that no preset should be used.

### --start-at

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string</code>                    |
| Environment | <code>$CODER_WORKSPACE_START_AT</code> |

Specify the workspace autostart schedule. Check coder schedule start --help for the syntax.

### --stop-after

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>duration</code>                    |
| Environment | <code>$CODER_WORKSPACE_STOP_AFTER</code> |

Specify a duration after which the workspace should shut down (e.g. 8h).

### --automatic-updates

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>string</code>                             |
| Environment | <code>$CODER_WORKSPACE_AUTOMATIC_UPDATES</code> |
| Default     | <code>never</code>                              |

Specify automatic updates setting for the workspace (accepts 'always' or 'never').

### --copy-parameters-from

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>string</code>                                |
| Environment | <code>$CODER_WORKSPACE_COPY_PARAMETERS_FROM</code> |

Specify the source workspace name to copy parameters from.

### --no-wait

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>bool</code>                  |
| Environment | <code>$CODER_CREATE_NO_WAIT</code> |

Return immediately after creating the workspace. The build will run in the background.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

### --build-option

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string-array</code>        |
| Environment | <code>$CODER_BUILD_OPTION</code> |

Build option value in the format "name=value".

### --build-options

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Prompt for one-time build options defined with ephemeral parameters.

### --ephemeral-parameter

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string-array</code>               |
| Environment | <code>$CODER_EPHEMERAL_PARAMETER</code> |

Set the value of ephemeral parameters defined in the template. The format is "name=value".

### --prompt-ephemeral-parameters

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>bool</code>                               |
| Environment | <code>$CODER_PROMPT_EPHEMERAL_PARAMETERS</code> |

Prompt to set values of ephemeral parameters defined in the template. If a value has been set via --ephemeral-parameter, it will not be prompted for.

### --parameter

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>string-array</code>          |
| Environment | <code>$CODER_RICH_PARAMETER</code> |

Rich parameter value in the format "name=value".

### --rich-parameter-file

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_RICH_PARAMETER_FILE</code> |

Specify a file path with values for rich parameters defined in the template. The file should be in YAML format, containing key-value pairs for the parameters.

### --parameter-default

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string-array</code>                  |
| Environment | <code>$CODER_RICH_PARAMETER_DEFAULT</code> |

Rich parameter default values in the format "name=value".

### --use-parameter-defaults

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>bool</code>                                    |
| Environment | <code>$CODER_WORKSPACE_USE_PARAMETER_DEFAULTS</code> |

Automatically accept parameter defaults when no value is provided.

### --always-prompt

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Always prompt all parameters. Does not pull parameter values from existing workspace.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder delete

Source: https://coder.com/docs/reference/cli/delete

<!-- DO NOT EDIT | GENERATED CONTENT -->

Delete a workspace

Aliases:

* rm

## Usage

```console
coder delete [flags] <workspace>
```

## Description

```console
  - Delete a workspace for another user (if you have permission):

     $ coder delete <username>/<workspace_name>
```

## Options

### --orphan

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Delete a workspace without deleting its resources. This can delete a workspace in a broken state, but may also lead to unaccounted cloud resources.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder dotfiles

Source: https://coder.com/docs/reference/cli/dotfiles

<!-- DO NOT EDIT | GENERATED CONTENT -->

Personalize your workspace by applying a canonical dotfiles repository

## Usage

```console
coder dotfiles [flags] <git_repo_url>
```

## Description

```console
  - Check out and install a dotfiles repository without prompts:

     $ coder dotfiles --yes git@github.com:example/dotfiles.git
```

## Options

### --symlink-dir

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>string</code>             |
| Environment | <code>$CODER_SYMLINK_DIR</code> |

Specifies the directory for the dotfiles symlink destinations. If empty, will use $HOME.

### -b, --branch

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Specifies which branch to clone. If empty, will default to cloning the default branch or using the existing branch in the cloned repo on disk.

### --repo-dir

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string</code>                   |
| Environment | <code>$CODER_DOTFILES_REPO_DIR</code> |
| Default     | <code>dotfiles</code>                 |

Specifies the directory for the dotfiles repository, relative to global config directory.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder external-auth

Source: https://coder.com/docs/reference/cli/external-auth

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage external authentication

## Usage

```console
coder external-auth
```

## Description

```console
Authenticate with external services inside of a workspace.
```

## Subcommands

| Name                                           | Purpose                             |
|------------------------------------------------|-------------------------------------|
| [<code>access-token</code>](./access-token.md) | Print auth for an external provider |

---

# coder external-auth access-token

Source: https://coder.com/docs/reference/cli/external-auth/access-token

<!-- DO NOT EDIT | GENERATED CONTENT -->

Print auth for an external provider

## Usage

```console
coder external-auth access-token [flags] <provider>
```

## Description

```console
Print an access-token for an external auth provider. The access-token will be validated and sent to stdout with exit code 0. If a valid access-token cannot be obtained, the URL to authenticate will be sent to stdout with exit code 1
  - Ensure that the user is authenticated with GitHub before cloning.:

     $ #!/usr/bin/env sh

OUTPUT=$(coder external-auth access-token github)
if [ $? -eq 0 ]; then
  echo "Authenticated with GitHub"
else
  echo "Please authenticate with GitHub:"
  echo $OUTPUT
fi


  - Obtain an extra property of an access token for additional metadata.:

     $ coder external-auth access-token slack --extra "authed_user.id"

  - Print the full token response as JSON.:

     $ coder external-auth access-token github --output json
```

## Options

### --extra

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Extract a field from the "extra" properties of the OAuth token.

### --output

|         |                         |
|---------|-------------------------|
| Type    | <code>text\|json</code> |
| Default | <code>text</code>       |

Output format. Available formats: text, json.

### --agent-token

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>string</code>             |
| Environment | <code>$CODER_AGENT_TOKEN</code> |

An agent authentication token.

### --agent-token-file

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string</code>                  |
| Environment | <code>$CODER_AGENT_TOKEN_FILE</code> |

A file containing an agent authentication token.

### --agent-url

|             |                               |
|-------------|-------------------------------|
| Type        | <code>url</code>              |
| Environment | <code>$CODER_AGENT_URL</code> |

URL for an agent to access your deployment.

### --auth

|             |                                |
|-------------|--------------------------------|
| Type        | <code>string</code>            |
| Environment | <code>$CODER_AGENT_AUTH</code> |
| Default     | <code>token</code>             |

Specify the authentication type to use for the agent.

### --agent-name

|             |                                |
|-------------|--------------------------------|
| Type        | <code>string</code>            |
| Environment | <code>$CODER_AGENT_NAME</code> |

The name of the agent to authenticate as (only applicable for instance identity).

---

# coder external-workspaces

Source: https://coder.com/docs/reference/cli/external-workspaces

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create or manage external workspaces

## Usage

```console
coder external-workspaces [flags] [subcommand]
```

## Subcommands

| Name                                                       | Purpose                                    |
|------------------------------------------------------------|--------------------------------------------|
| [<code>create</code>](./create.md)                         | Create a new external workspace            |
| [<code>agent-instructions</code>](./agent-instructions.md) | Get the instructions for an external agent |
| [<code>list</code>](./list.md)                             | List external workspaces                   |

## Options

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder external-workspaces agent-instructions

Source: https://coder.com/docs/reference/cli/external-workspaces/agent-instructions

<!-- DO NOT EDIT | GENERATED CONTENT -->

Get the instructions for an external agent

## Usage

```console
coder external-workspaces agent-instructions [flags] [user/]workspace[.agent]
```

## Options

### -o, --output

|         |                         |
|---------|-------------------------|
| Type    | <code>text\|json</code> |
| Default | <code>text</code>       |

Output format.

---

# coder external-workspaces create

Source: https://coder.com/docs/reference/cli/external-workspaces/create

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create a new external workspace

## Usage

```console
coder external-workspaces create [flags] [workspace]
```

## Description

```console
  - Create a workspace for another user (if you have permission):

     $ coder create <username>/<workspace_name>
```

## Options

### -t, --template

|             |                                   |
|-------------|-----------------------------------|
| Type        | <code>string</code>               |
| Environment | <code>$CODER_TEMPLATE_NAME</code> |

Specify a template name.

### --template-version

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string</code>                  |
| Environment | <code>$CODER_TEMPLATE_VERSION</code> |

Specify a template version name.

### --preset

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>string</code>             |
| Environment | <code>$CODER_PRESET_NAME</code> |

Specify the name of a template version preset. Use 'none' to explicitly indicate that no preset should be used.

### --start-at

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string</code>                    |
| Environment | <code>$CODER_WORKSPACE_START_AT</code> |

Specify the workspace autostart schedule. Check coder schedule start --help for the syntax.

### --stop-after

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>duration</code>                    |
| Environment | <code>$CODER_WORKSPACE_STOP_AFTER</code> |

Specify a duration after which the workspace should shut down (e.g. 8h).

### --automatic-updates

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>string</code>                             |
| Environment | <code>$CODER_WORKSPACE_AUTOMATIC_UPDATES</code> |
| Default     | <code>never</code>                              |

Specify automatic updates setting for the workspace (accepts 'always' or 'never').

### --copy-parameters-from

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>string</code>                                |
| Environment | <code>$CODER_WORKSPACE_COPY_PARAMETERS_FROM</code> |

Specify the source workspace name to copy parameters from.

### --no-wait

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>bool</code>                  |
| Environment | <code>$CODER_CREATE_NO_WAIT</code> |

Return immediately after creating the workspace. The build will run in the background.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

### --build-option

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string-array</code>        |
| Environment | <code>$CODER_BUILD_OPTION</code> |

Build option value in the format "name=value".

### --build-options

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Prompt for one-time build options defined with ephemeral parameters.

### --ephemeral-parameter

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string-array</code>               |
| Environment | <code>$CODER_EPHEMERAL_PARAMETER</code> |

Set the value of ephemeral parameters defined in the template. The format is "name=value".

### --prompt-ephemeral-parameters

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>bool</code>                               |
| Environment | <code>$CODER_PROMPT_EPHEMERAL_PARAMETERS</code> |

Prompt to set values of ephemeral parameters defined in the template. If a value has been set via --ephemeral-parameter, it will not be prompted for.

### --parameter

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>string-array</code>          |
| Environment | <code>$CODER_RICH_PARAMETER</code> |

Rich parameter value in the format "name=value".

### --rich-parameter-file

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_RICH_PARAMETER_FILE</code> |

Specify a file path with values for rich parameters defined in the template. The file should be in YAML format, containing key-value pairs for the parameters.

### --parameter-default

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string-array</code>                  |
| Environment | <code>$CODER_RICH_PARAMETER_DEFAULT</code> |

Rich parameter default values in the format "name=value".

### --use-parameter-defaults

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>bool</code>                                    |
| Environment | <code>$CODER_WORKSPACE_USE_PARAMETER_DEFAULTS</code> |

Automatically accept parameter defaults when no value is provided.

### --always-prompt

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Always prompt all parameters. Does not pull parameter values from existing workspace.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder external-workspaces list

Source: https://coder.com/docs/reference/cli/external-workspaces/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List external workspaces

Aliases:

* ls

## Usage

```console
coder external-workspaces list [flags]
```

## Options

### -a, --all

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Specifies whether all workspaces will be listed or not.

### --search

|         |                      |
|---------|----------------------|
| Type    | <code>string</code>  |
| Default | <code>user:me</code> |

Search for a workspace with a query.

### -c, --column

|         |                                                                                                                                                                                                       |
|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[favorite\|workspace\|organization id\|organization name\|template\|status\|healthy\|last built\|current version\|outdated\|starts at\|starts next\|stops after\|stops next\|daily cost]</code> |
| Default | <code>workspace,template,status,healthy,last built,current version,outdated</code>                                                                                                                    |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder favorite

Source: https://coder.com/docs/reference/cli/favorite

<!-- DO NOT EDIT | GENERATED CONTENT -->

Add a workspace to your favorites

Aliases:

* fav
* favourite

## Usage

```console
coder favorite <workspace>
```

---

# coder features

Source: https://coder.com/docs/reference/cli/features

<!-- DO NOT EDIT | GENERATED CONTENT -->

List Enterprise features

Aliases:

* feature

## Usage

```console
coder features
```

## Subcommands

| Name                           | Purpose |
|--------------------------------|---------|
| [<code>list</code>](./list.md) |         |

---

# coder features list

Source: https://coder.com/docs/reference/cli/features/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

Aliases:

* ls

## Usage

```console
coder features list [flags]
```

## Options

### -c, --column

|         |                                                          |
|---------|----------------------------------------------------------|
| Type    | <code>[name\|entitlement\|enabled\|limit\|actual]</code> |
| Default | <code>name,entitlement,enabled,limit,actual</code>       |

Specify columns to filter in the table.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder groups

Source: https://coder.com/docs/reference/cli/groups

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage groups

Aliases:

* group

## Usage

```console
coder groups
```

## Subcommands

| Name                               | Purpose             |
|------------------------------------|---------------------|
| [<code>create</code>](./create.md) | Create a user group |
| [<code>list</code>](./list.md)     | List user groups    |
| [<code>edit</code>](./edit.md)     | Edit a user group   |
| [<code>delete</code>](./delete.md) | Delete a user group |

---

# coder groups create

Source: https://coder.com/docs/reference/cli/groups/create

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create a user group

## Usage

```console
coder groups create [flags] <name>
```

## Options

### -u, --avatar-url

|             |                                |
|-------------|--------------------------------|
| Type        | <code>string</code>            |
| Environment | <code>$CODER_AVATAR_URL</code> |

Set an avatar for a group.

### --display-name

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_DISPLAY_NAME</code> |

Optional human friendly name for the group.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder groups delete

Source: https://coder.com/docs/reference/cli/groups/delete

<!-- DO NOT EDIT | GENERATED CONTENT -->

Delete a user group

Aliases:

* rm

## Usage

```console
coder groups delete [flags] <name>
```

## Options

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder groups edit

Source: https://coder.com/docs/reference/cli/groups/edit

<!-- DO NOT EDIT | GENERATED CONTENT -->

Edit a user group

## Usage

```console
coder groups edit [flags] <name>
```

## Options

### -n, --name

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Update the group name.

### -u, --avatar-url

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Update the group avatar.

### --display-name

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_DISPLAY_NAME</code> |

Optional human friendly name for the group.

### -a, --add-users

|      |                           |
|------|---------------------------|
| Type | <code>string-array</code> |

Add users to the group. Accepts emails or IDs.

### -r, --rm-users

|      |                           |
|------|---------------------------|
| Type | <code>string-array</code> |

Remove users to the group. Accepts emails or IDs.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder groups list

Source: https://coder.com/docs/reference/cli/groups/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List user groups

## Usage

```console
coder groups list [flags]
```

## Options

### -c, --column

|         |                                                                         |
|---------|-------------------------------------------------------------------------|
| Type    | <code>[name\|display name\|organization id\|members\|avatar url]</code> |
| Default | <code>name,display name,organization id,members,avatar url</code>       |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder licenses

Source: https://coder.com/docs/reference/cli/licenses

<!-- DO NOT EDIT | GENERATED CONTENT -->

Add, delete, and list licenses

Aliases:

* license

## Usage

```console
coder licenses
```

## Subcommands

| Name                               | Purpose                           |
|------------------------------------|-----------------------------------|
| [<code>add</code>](./add.md)       | Add license to Coder deployment   |
| [<code>list</code>](./list.md)     | List licenses (including expired) |
| [<code>delete</code>](./delete.md) | Delete license by ID              |

---

# coder licenses add

Source: https://coder.com/docs/reference/cli/licenses/add

<!-- DO NOT EDIT | GENERATED CONTENT -->

Add license to Coder deployment

## Usage

```console
coder licenses add [flags] [-f file | -l license]
```

## Options

### -f, --file

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Load license from file.

### -l, --license

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

License string.

### --debug

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Output license claims for debugging.

---

# coder licenses delete

Source: https://coder.com/docs/reference/cli/licenses/delete

<!-- DO NOT EDIT | GENERATED CONTENT -->

Delete license by ID

Aliases:

* del
* rm

## Usage

```console
coder licenses delete <id>
```

---

# coder licenses list

Source: https://coder.com/docs/reference/cli/licenses/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List licenses (including expired)

Aliases:

* ls

## Usage

```console
coder licenses list [flags]
```

## Options

### -c, --column

|         |                                                                   |
|---------|-------------------------------------------------------------------|
| Type    | <code>[id\|uuid\|uploaded at\|features\|expires at\|trial]</code> |
| Default | <code>ID,UUID,Expires At,Uploaded At,Features</code>              |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder list

Source: https://coder.com/docs/reference/cli/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List workspaces

Aliases:

* ls

## Usage

```console
coder list [flags]
```

## Options

### -a, --all

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Specifies whether all workspaces will be listed or not.

### --search

|         |                      |
|---------|----------------------|
| Type    | <code>string</code>  |
| Default | <code>user:me</code> |

Search for a workspace with a query.

### -c, --column

|         |                                                                                                                                                                                                       |
|---------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[favorite\|workspace\|organization id\|organization name\|template\|status\|healthy\|last built\|current version\|outdated\|starts at\|starts next\|stops after\|stops next\|daily cost]</code> |
| Default | <code>workspace,template,status,healthy,last built,current version,outdated,starts at,stops after</code>                                                                                              |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder login

Source: https://coder.com/docs/reference/cli/login

<!-- DO NOT EDIT | GENERATED CONTENT -->

Authenticate with Coder deployment

## Usage

```console
coder login [flags] [<url>]
```

## Description

```console
By default, the session token is stored in the operating system keyring on macOS and Windows and a plain text file on Linux. Use the --use-keyring flag or CODER_USE_KEYRING environment variable to change the storage mechanism.
```

## Subcommands

| Name                             | Purpose                         |
|----------------------------------|---------------------------------|
| [<code>token</code>](./token.md) | Print the current session token |

## Options

### --first-user-email

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string</code>                  |
| Environment | <code>$CODER_FIRST_USER_EMAIL</code> |

Specifies an email address to use if creating the first user for the deployment.

### --first-user-username

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_FIRST_USER_USERNAME</code> |

Specifies a username to use if creating the first user for the deployment.

### --first-user-full-name

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_FIRST_USER_FULL_NAME</code> |

Specifies a human-readable name for the first user of the deployment.

### --first-user-password

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_FIRST_USER_PASSWORD</code> |

Specifies a password to use if creating the first user for the deployment.

### --first-user-trial

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>bool</code>                    |
| Environment | <code>$CODER_FIRST_USER_TRIAL</code> |

Specifies whether a trial license should be provisioned for the Coder deployment or not.

### --first-user-trial-first-name

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>string</code>                             |
| Environment | <code>$CODER_FIRST_USER_TRIAL_FIRST_NAME</code> |

Specifies the first name of the first user for the deployment. Only used if --first-user-trial is set.

### --first-user-trial-last-name

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>string</code>                            |
| Environment | <code>$CODER_FIRST_USER_TRIAL_LAST_NAME</code> |

Specifies the last name of the first user for the deployment. Only used if --first-user-trial is set.

### --first-user-trial-phone-number

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>string</code>                               |
| Environment | <code>$CODER_FIRST_USER_TRIAL_PHONE_NUMBER</code> |

Specifies the phone number of the first user for the deployment. Only used if --first-user-trial is set.

### --first-user-trial-job-title

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>string</code>                            |
| Environment | <code>$CODER_FIRST_USER_TRIAL_JOB_TITLE</code> |

Specifies the job title of the first user for the deployment. Only used if --first-user-trial is set.

### --first-user-trial-company-name

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>string</code>                               |
| Environment | <code>$CODER_FIRST_USER_TRIAL_COMPANY_NAME</code> |

Specifies the company name of the first user for the deployment. Only used if --first-user-trial is set.

### --first-user-trial-country

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>string</code>                          |
| Environment | <code>$CODER_FIRST_USER_TRIAL_COUNTRY</code> |

Specifies the country of the first user for the deployment. Only used if --first-user-trial is set.

### --first-user-trial-developers

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>string</code>                             |
| Environment | <code>$CODER_FIRST_USER_TRIAL_DEVELOPERS</code> |

Specifies the number of developers using the deployment. Only used if --first-user-trial is set.

### --use-token-as-session

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

By default, the CLI will generate a new session token when logging in. This flag will instead use the provided token as the session token.

---

# coder login token

Source: https://coder.com/docs/reference/cli/login/token

<!-- DO NOT EDIT | GENERATED CONTENT -->

Print the current session token

## Usage

```console
coder login token
```

## Description

```console
Print the session token for use in scripts and automation.
```

---

# coder logout

Source: https://coder.com/docs/reference/cli/logout

<!-- DO NOT EDIT | GENERATED CONTENT -->

Unauthenticate your local session

## Usage

```console
coder logout [flags]
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder logs

Source: https://coder.com/docs/reference/cli/logs

<!-- DO NOT EDIT | GENERATED CONTENT -->

View logs for a workspace

## Usage

```console
coder logs [flags] <workspace>
```

## Description

```console
View logs for a workspace
```

## Options

### -n, --build-number

|         |                  |
|---------|------------------|
| Type    | <code>int</code> |
| Default | <code>0</code>   |

Only show logs for a specific build number. Defaults to 0, which maps to the most recent build (build numbers start at 1). Negative values are treated as offsets—for example, -1 refers to the previous build.

### -f, --follow

|         |                    |
|---------|--------------------|
| Type    | <code>bool</code>  |
| Default | <code>false</code> |

Follow logs as they are emitted.

---

# coder netcheck

Source: https://coder.com/docs/reference/cli/netcheck

<!-- DO NOT EDIT | GENERATED CONTENT -->

Print network debug information for DERP and STUN

## Usage

```console
coder netcheck
```

---

# coder notifications

Source: https://coder.com/docs/reference/cli/notifications

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage Coder notifications

Aliases:

* notification

## Usage

```console
coder notifications
```

## Description

```console
Administrators can use these commands to change notification settings.
  - Pause Coder notifications. Administrators can temporarily stop notifiers from
dispatching messages in case of the target outage (for example: unavailable SMTP
server or Webhook not responding):

     $ coder notifications pause

  - Resume Coder notifications:

     $ coder notifications resume

  - Send a test notification. Administrators can use this to verify the notification
target settings:

     $ coder notifications test

  - Send a custom notification to the requesting user. Sending notifications
targeting other users or groups is currently not supported:

     $ coder notifications custom "Custom Title" "Custom Message"
```

## Subcommands

| Name                               | Purpose                    |
|------------------------------------|----------------------------|
| [<code>pause</code>](./pause.md)   | Pause notifications        |
| [<code>resume</code>](./resume.md) | Resume notifications       |
| [<code>test</code>](./test.md)     | Send a test notification   |
| [<code>custom</code>](./custom.md) | Send a custom notification |

---

# coder notifications custom

Source: https://coder.com/docs/reference/cli/notifications/custom

<!-- DO NOT EDIT | GENERATED CONTENT -->

Send a custom notification

## Usage

```console
coder notifications custom <title> <message>
```

---

# coder notifications pause

Source: https://coder.com/docs/reference/cli/notifications/pause

<!-- DO NOT EDIT | GENERATED CONTENT -->

Pause notifications

## Usage

```console
coder notifications pause
```

---

# coder notifications resume

Source: https://coder.com/docs/reference/cli/notifications/resume

<!-- DO NOT EDIT | GENERATED CONTENT -->

Resume notifications

## Usage

```console
coder notifications resume
```

---

# coder notifications test

Source: https://coder.com/docs/reference/cli/notifications/test

<!-- DO NOT EDIT | GENERATED CONTENT -->

Send a test notification

## Usage

```console
coder notifications test
```

---

# coder oauth2-provider

Source: https://coder.com/docs/reference/cli/oauth2-provider

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage Coder OAuth2 provider settings

## Usage

```console
coder oauth2-provider
```

## Description

```console
Administrators can use these commands to change OAuth2 provider settings.
  - Enable dynamic client registration (RFC 7591), allowing OAuth2/MCP clients to
self-register without an admin creating an app first:

     $ coder oauth2-provider dcr enable

  - Disable dynamic client registration. Clients that already registered are
unaffected; only new self-registration attempts are rejected:

     $ coder oauth2-provider dcr disable
```

## Subcommands

| Name                               | Purpose                                              |
|------------------------------------|------------------------------------------------------|
| [<code>dcr</code>](./dcr/index.md) | Manage OAuth2 dynamic client registration (RFC 7591) |

---

# coder oauth2-provider dcr

Source: https://coder.com/docs/reference/cli/oauth2-provider/dcr

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage OAuth2 dynamic client registration (RFC 7591)

## Usage

```console
coder oauth2-provider dcr
```

## Subcommands

| Name                                 | Purpose                                    |
|--------------------------------------|--------------------------------------------|
| [<code>enable</code>](./enable.md)   | Enable OAuth2 dynamic client registration  |
| [<code>disable</code>](./disable.md) | Disable OAuth2 dynamic client registration |

---

# coder oauth2-provider dcr disable

Source: https://coder.com/docs/reference/cli/oauth2-provider/dcr/disable

<!-- DO NOT EDIT | GENERATED CONTENT -->

Disable OAuth2 dynamic client registration

## Usage

```console
coder oauth2-provider dcr disable
```

---

# coder oauth2-provider dcr enable

Source: https://coder.com/docs/reference/cli/oauth2-provider/dcr/enable

<!-- DO NOT EDIT | GENERATED CONTENT -->

Enable OAuth2 dynamic client registration

## Usage

```console
coder oauth2-provider dcr enable
```

---

# coder open

Source: https://coder.com/docs/reference/cli/open

<!-- DO NOT EDIT | GENERATED CONTENT -->

Open a workspace

## Usage

```console
coder open
```

## Subcommands

| Name                               | Purpose                             |
|------------------------------------|-------------------------------------|
| [<code>vscode</code>](./vscode.md) | Open a workspace in VS Code Desktop |
| [<code>app</code>](./app.md)       | Open a workspace application.       |

---

# coder open app

Source: https://coder.com/docs/reference/cli/open/app

<!-- DO NOT EDIT | GENERATED CONTENT -->

Open a workspace application.

## Usage

```console
coder open app [flags] <workspace> <app slug>
```

## Options

### --region

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string</code>                 |
| Environment | <code>$CODER_OPEN_APP_REGION</code> |
| Default     | <code>primary</code>                |

Region to use when opening the app. By default, the app will be opened using the main Coder deployment (a.k.a. "primary").

---

# coder open vscode

Source: https://coder.com/docs/reference/cli/open/vscode

<!-- DO NOT EDIT | GENERATED CONTENT -->

Open a workspace in VS Code Desktop

## Usage

```console
coder open vscode [flags] <workspace> [<directory in workspace>]
```

## Options

### --generate-token

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>bool</code>                              |
| Environment | <code>$CODER_OPEN_VSCODE_GENERATE_TOKEN</code> |

Generate an auth token and include it in the vscode:// URI. This is for automagical configuration of VS Code Desktop and not needed if already configured. This flag does not need to be specified when running this command on a local machine unless automatic open fails.

---

# coder organizations

Source: https://coder.com/docs/reference/cli/organizations

<!-- DO NOT EDIT | GENERATED CONTENT -->

Organization related commands

Aliases:

* organization
* org
* orgs

## Usage

```console
coder organizations [flags] [subcommand]
```

## Subcommands

| Name                                         | Purpose                                                                                                                                                        |
|----------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [<code>show</code>](./show.md)               | Show the organization. Using "selected" will show the selected organization from the "--org" flag. Using "me" will show all organizations you are a member of. |
| [<code>list</code>](./list.md)               | List all organizations                                                                                                                                         |
| [<code>create</code>](./create.md)           | Create a new organization.                                                                                                                                     |
| [<code>edit</code>](./edit.md)               | Edit organization settings.                                                                                                                                    |
| [<code>delete</code>](./delete.md)           | Delete an organization                                                                                                                                         |
| [<code>members</code>](./members/index.md)   | Manage organization members                                                                                                                                    |
| [<code>roles</code>](./roles/index.md)       | Manage organization roles.                                                                                                                                     |
| [<code>settings</code>](./settings/index.md) | Manage organization settings.                                                                                                                                  |

## Options

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder organizations create

Source: https://coder.com/docs/reference/cli/organizations/create

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create a new organization.

## Usage

```console
coder organizations create [flags] <organization name>
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder organizations delete

Source: https://coder.com/docs/reference/cli/organizations/delete

<!-- DO NOT EDIT | GENERATED CONTENT -->

Delete an organization

Aliases:

* rm

## Usage

```console
coder organizations delete [flags] <organization_name_or_id>
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder organizations edit

Source: https://coder.com/docs/reference/cli/organizations/edit

<!-- DO NOT EDIT | GENERATED CONTENT -->

Edit organization settings.

## Usage

```console
coder organizations edit [flags]
```

## Description

```console
  - Replace the roles every member of the organization holds:

     $ coder organizations edit --default-org-member-roles organization-workspace-access,agents-access,organization-template-admin

  - Restrict Coder Agents to members assigned agents-access directly:

     $ coder organizations edit --default-org-member-roles organization-workspace-access

  - Grant members no roles at all:

     $ coder organizations edit --default-org-member-roles ""
```

## Options

### --default-org-member-roles

|      |                           |
|------|---------------------------|
| Type | <code>string-array</code> |

Replaces the roles every member of the organization holds. Accepts a comma-separated list and may be repeated. An empty value removes every role. New organizations start with organization-workspace-access, which grants members access to their own workspaces, and agents-access, which grants members access to Coder Agents.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder organizations list

Source: https://coder.com/docs/reference/cli/organizations/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List all organizations

Aliases:

* ls

## Usage

```console
coder organizations list [flags]
```

## Description

```console
List all organizations. Requires a role which grants ResourceOrganization: read.
```

## Options

### -c, --column

|         |                                                                                                                     |
|---------|---------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[id\|name\|display name\|icon\|description\|created at\|updated at\|default\|default org member roles]</code> |
| Default | <code>name,display name,id,default</code>                                                                           |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder organizations members

Source: https://coder.com/docs/reference/cli/organizations/members

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage organization members

Aliases:

* member

## Usage

```console
coder organizations members
```

## Subcommands

| Name                                       | Purpose                                         |
|--------------------------------------------|-------------------------------------------------|
| [<code>list</code>](./list.md)             | List all organization members                   |
| [<code>edit-roles</code>](./edit-roles.md) | Edit organization member's roles                |
| [<code>add</code>](./add.md)               | Add a new member to the current organization    |
| [<code>remove</code>](./remove.md)         | Remove a new member to the current organization |

---

# coder organizations members add

Source: https://coder.com/docs/reference/cli/organizations/members/add

<!-- DO NOT EDIT | GENERATED CONTENT -->

Add a new member to the current organization

## Usage

```console
coder organizations members add <username | user_id>
```

---

# coder organizations members edit-roles

Source: https://coder.com/docs/reference/cli/organizations/members/edit-roles

<!-- DO NOT EDIT | GENERATED CONTENT -->

Edit organization member's roles

Aliases:

* edit-role

## Usage

```console
coder organizations members edit-roles <username | user_id> [roles...]
```

---

# coder organizations members list

Source: https://coder.com/docs/reference/cli/organizations/members/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List all organization members

## Usage

```console
coder organizations members list [flags]
```

## Options

### -c, --column

|         |                                                                                                                                                     |
|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[username\|name\|last seen at\|user created at\|user updated at\|user id\|organization id\|created at\|updated at\|organization roles]</code> |
| Default | <code>username,organization roles</code>                                                                                                            |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder organizations members remove

Source: https://coder.com/docs/reference/cli/organizations/members/remove

<!-- DO NOT EDIT | GENERATED CONTENT -->

Remove a new member to the current organization

Aliases:

* rm

## Usage

```console
coder organizations members remove <username | user_id>
```

---

# coder organizations roles

Source: https://coder.com/docs/reference/cli/organizations/roles

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage organization roles.

Aliases:

* role

## Usage

```console
coder organizations roles
```

## Subcommands

| Name                               | Purpose                               |
|------------------------------------|---------------------------------------|
| [<code>show</code>](./show.md)     | Show role(s)                          |
| [<code>update</code>](./update.md) | Update an organization custom role    |
| [<code>create</code>](./create.md) | Create a new organization custom role |

---

# coder organizations roles create

Source: https://coder.com/docs/reference/cli/organizations/roles/create

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create a new organization custom role

## Usage

```console
coder organizations roles create [flags] <role_name>
```

## Description

```console
  - Run with an input.json file:

     $ coder organization -O <organization_name> roles create --stdin < role.json
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

### --dry-run

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Does all the work, but does not submit the final updated role.

### --stdin

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Reads stdin for the json role definition to upload.

---

# coder organizations roles show

Source: https://coder.com/docs/reference/cli/organizations/roles/show

<!-- DO NOT EDIT | GENERATED CONTENT -->

Show role(s)

## Usage

```console
coder organizations roles show [flags] [role_names ...]
```

## Options

### -c, --column

|         |                                                                                                                  |
|---------|------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[name\|display name\|organization id\|site permissions\|organization permissions\|user permissions]</code> |
| Default | <code>name,display name,site permissions,organization permissions,user permissions</code>                        |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder organizations roles update

Source: https://coder.com/docs/reference/cli/organizations/roles/update

<!-- DO NOT EDIT | GENERATED CONTENT -->

Update an organization custom role

## Usage

```console
coder organizations roles update [flags] <role_name>
```

## Description

```console
  - Run with an input.json file:

     $ coder roles update --stdin < role.json
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

### --dry-run

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Does all the work, but does not submit the final updated role.

### --stdin

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Reads stdin for the json role definition to upload.

### -c, --column

|         |                                                                                                                  |
|---------|------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[name\|display name\|organization id\|site permissions\|organization permissions\|user permissions]</code> |
| Default | <code>name,display name,site permissions,organization permissions,user permissions</code>                        |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder organizations settings

Source: https://coder.com/docs/reference/cli/organizations/settings

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage organization settings.

Aliases:

* setting

## Usage

```console
coder organizations settings
```

## Subcommands

| Name                                 | Purpose                                 |
|--------------------------------------|-----------------------------------------|
| [<code>show</code>](./show/index.md) | Outputs specified organization setting. |
| [<code>set</code>](./set/index.md)   | Update specified organization setting.  |

---

# coder organizations settings set

Source: https://coder.com/docs/reference/cli/organizations/settings/set

<!-- DO NOT EDIT | GENERATED CONTENT -->

Update specified organization setting.

## Usage

```console
coder organizations settings set
```

## Description

```console
  - Update group sync settings.:

     $ coder organization settings set groupsync < input.json
```

## Subcommands

| Name                                                     | Purpose                                                                  |
|----------------------------------------------------------|--------------------------------------------------------------------------|
| [<code>group-sync</code>](./group-sync.md)               | Group sync settings to sync groups from an IdP.                          |
| [<code>role-sync</code>](./role-sync.md)                 | Role sync settings to sync organization roles from an IdP.               |
| [<code>organization-sync</code>](./organization-sync.md) | Organization sync settings to sync organization memberships from an IdP. |
| [<code>workspace-sharing</code>](./workspace-sharing.md) | Workspace sharing settings for the organization.                         |

---

# coder organizations settings set group-sync

Source: https://coder.com/docs/reference/cli/organizations/settings/set/group-sync

<!-- DO NOT EDIT | GENERATED CONTENT -->

Group sync settings to sync groups from an IdP.

Aliases:

* groupsync

## Usage

```console
coder organizations settings set group-sync
```

---

# coder organizations settings set organization-sync

Source: https://coder.com/docs/reference/cli/organizations/settings/set/organization-sync

<!-- DO NOT EDIT | GENERATED CONTENT -->

Organization sync settings to sync organization memberships from an IdP.

Aliases:

* organizationsync
* org-sync
* orgsync

## Usage

```console
coder organizations settings set organization-sync
```

---

# coder organizations settings set role-sync

Source: https://coder.com/docs/reference/cli/organizations/settings/set/role-sync

<!-- DO NOT EDIT | GENERATED CONTENT -->

Role sync settings to sync organization roles from an IdP.

Aliases:

* rolesync

## Usage

```console
coder organizations settings set role-sync
```

---

# coder organizations settings set workspace-sharing

Source: https://coder.com/docs/reference/cli/organizations/settings/set/workspace-sharing

<!-- DO NOT EDIT | GENERATED CONTENT -->

Workspace sharing settings for the organization.

Aliases:

* workspacesharing

## Usage

```console
coder organizations settings set workspace-sharing
```

---

# coder organizations settings show

Source: https://coder.com/docs/reference/cli/organizations/settings/show

<!-- DO NOT EDIT | GENERATED CONTENT -->

Outputs specified organization setting.

## Usage

```console
coder organizations settings show
```

## Description

```console
  - Output group sync settings.:

     $ coder organization settings show groupsync
```

## Subcommands

| Name                                                     | Purpose                                                                  |
|----------------------------------------------------------|--------------------------------------------------------------------------|
| [<code>group-sync</code>](./group-sync.md)               | Group sync settings to sync groups from an IdP.                          |
| [<code>role-sync</code>](./role-sync.md)                 | Role sync settings to sync organization roles from an IdP.               |
| [<code>organization-sync</code>](./organization-sync.md) | Organization sync settings to sync organization memberships from an IdP. |
| [<code>workspace-sharing</code>](./workspace-sharing.md) | Workspace sharing settings for the organization.                         |

---

# coder organizations settings show group-sync

Source: https://coder.com/docs/reference/cli/organizations/settings/show/group-sync

<!-- DO NOT EDIT | GENERATED CONTENT -->

Group sync settings to sync groups from an IdP.

Aliases:

* groupsync

## Usage

```console
coder organizations settings show group-sync
```

---

# coder organizations settings show organization-sync

Source: https://coder.com/docs/reference/cli/organizations/settings/show/organization-sync

<!-- DO NOT EDIT | GENERATED CONTENT -->

Organization sync settings to sync organization memberships from an IdP.

Aliases:

* organizationsync
* org-sync
* orgsync

## Usage

```console
coder organizations settings show organization-sync
```

---

# coder organizations settings show role-sync

Source: https://coder.com/docs/reference/cli/organizations/settings/show/role-sync

<!-- DO NOT EDIT | GENERATED CONTENT -->

Role sync settings to sync organization roles from an IdP.

Aliases:

* rolesync

## Usage

```console
coder organizations settings show role-sync
```

---

# coder organizations settings show workspace-sharing

Source: https://coder.com/docs/reference/cli/organizations/settings/show/workspace-sharing

<!-- DO NOT EDIT | GENERATED CONTENT -->

Workspace sharing settings for the organization.

Aliases:

* workspacesharing

## Usage

```console
coder organizations settings show workspace-sharing
```

---

# coder organizations show

Source: https://coder.com/docs/reference/cli/organizations/show

<!-- DO NOT EDIT | GENERATED CONTENT -->

Show the organization. Using "selected" will show the selected organization from the "--org" flag. Using "me" will show all organizations you are a member of.

## Usage

```console
coder organizations show [flags] ["selected"|"me"|uuid|org_name]
```

## Description

```console
  - coder org show selected:

     $ Shows the organizations selected with '--org=<org_name>'. This organization is the organization used by the cli.

  - coder org show me:

     $ List of all organizations you are a member of.

  - coder org show developers:

     $ Show organization with name 'developers'

  - coder org show 90ee1875-3db5-43b3-828e-af3687522e43:

     $ Show organization with the given ID.
```

## Options

### --only-id

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Only print the organization ID.

### -c, --column

|         |                                                                                                                     |
|---------|---------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[id\|name\|display name\|icon\|description\|created at\|updated at\|default\|default org member roles]</code> |
| Default | <code>id,name,default</code>                                                                                        |

Columns to display in table output.

### -o, --output

|         |                                |
|---------|--------------------------------|
| Type    | <code>text\|table\|json</code> |
| Default | <code>text</code>              |

Output format.

---

# coder ping

Source: https://coder.com/docs/reference/cli/ping

<!-- DO NOT EDIT | GENERATED CONTENT -->

Ping a workspace

## Usage

```console
coder ping [flags] <workspace>
```

## Options

### --wait

|         |                       |
|---------|-----------------------|
| Type    | <code>duration</code> |
| Default | <code>1s</code>       |

Specifies how long to wait between pings.

### -t, --timeout

|         |                       |
|---------|-----------------------|
| Type    | <code>duration</code> |
| Default | <code>5s</code>       |

Specifies how long to wait for a ping to complete.

### -n, --num

|      |                  |
|------|------------------|
| Type | <code>int</code> |

Specifies the number of pings to perform. By default, pings will continue until interrupted.

### --time

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Show the response time of each pong in local time.

### --utc

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Show the response time of each pong in UTC (implies --time).

---

# coder port-forward

Source: https://coder.com/docs/reference/cli/port-forward

<!-- DO NOT EDIT | GENERATED CONTENT -->

Forward ports from a workspace to the local machine. For reverse port forwarding, use "coder ssh -R".

Aliases:

* tunnel

## Usage

```console
coder port-forward [flags] <workspace>
```

## Description

```console
  - Port forward a single TCP port from 1234 in the workspace to port 5678 on your
local machine:

     $ coder port-forward <workspace> --tcp 5678:1234

  - Port forward a single UDP port from port 9000 to port 9000 on your local
machine:

     $ coder port-forward <workspace> --udp 9000

  - Port forward multiple TCP ports and a UDP port:

     $ coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53

  - Port forward multiple ports (TCP or UDP) in condensed syntax:

     $ coder port-forward <workspace> --tcp 8080,9000:3000,9090-9092,10000-10002:10010-10012

  - Port forward specifying the local address to bind to:

     $ coder port-forward <workspace> --tcp 1.2.3.4:8080:8080
```

## Options

### -p, --tcp

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string-array</code>            |
| Environment | <code>$CODER_PORT_FORWARD_TCP</code> |

Forward TCP port(s) from the workspace to the local machine.

### --udp

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string-array</code>            |
| Environment | <code>$CODER_PORT_FORWARD_UDP</code> |

Forward UDP port(s) from the workspace to the local machine. The UDP connection has TCP-like semantics to support stateful UDP protocols.

### --disable-autostart

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>bool</code>                         |
| Environment | <code>$CODER_SSH_DISABLE_AUTOSTART</code> |
| Default     | <code>false</code>                        |

Disable starting the workspace automatically when connecting via SSH.

---

# coder prebuilds

Source: https://coder.com/docs/reference/cli/prebuilds

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage Coder prebuilds

Aliases:

* prebuild

## Usage

```console
coder prebuilds
```

## Description

```console
Administrators can use these commands to manage prebuilt workspace settings.
  - Pause Coder prebuilt workspace reconciliation.:

     $ coder prebuilds pause

  - Resume Coder prebuilt workspace reconciliation if it has been paused.:

     $ coder prebuilds resume
```

## Subcommands

| Name                               | Purpose          |
|------------------------------------|------------------|
| [<code>pause</code>](./pause.md)   | Pause prebuilds  |
| [<code>resume</code>](./resume.md) | Resume prebuilds |

---

# coder prebuilds pause

Source: https://coder.com/docs/reference/cli/prebuilds/pause

<!-- DO NOT EDIT | GENERATED CONTENT -->

Pause prebuilds

## Usage

```console
coder prebuilds pause
```

---

# coder prebuilds resume

Source: https://coder.com/docs/reference/cli/prebuilds/resume

<!-- DO NOT EDIT | GENERATED CONTENT -->

Resume prebuilds

## Usage

```console
coder prebuilds resume
```

---

# coder provisioner

Source: https://coder.com/docs/reference/cli/provisioner

<!-- DO NOT EDIT | GENERATED CONTENT -->

View and manage provisioner daemons and jobs

Aliases:

* provisioners

## Usage

```console
coder provisioner
```

## Subcommands

| Name                                 | Purpose                                     |
|--------------------------------------|---------------------------------------------|
| [<code>list</code>](./list.md)       | List provisioner daemons in an organization |
| [<code>jobs</code>](./jobs/index.md) | View and manage provisioner jobs            |
| [<code>start</code>](./start.md)     | Run a provisioner daemon                    |
| [<code>keys</code>](./keys/index.md) | Manage provisioner keys                     |

---

# coder provisioner jobs

Source: https://coder.com/docs/reference/cli/provisioner/jobs

<!-- DO NOT EDIT | GENERATED CONTENT -->

View and manage provisioner jobs

Aliases:

* job

## Usage

```console
coder provisioner jobs
```

## Subcommands

| Name                               | Purpose                  |
|------------------------------------|--------------------------|
| [<code>cancel</code>](./cancel.md) | Cancel a provisioner job |
| [<code>list</code>](./list.md)     | List provisioner jobs    |

---

# coder provisioner jobs cancel

Source: https://coder.com/docs/reference/cli/provisioner/jobs/cancel

<!-- DO NOT EDIT | GENERATED CONTENT -->

Cancel a provisioner job

## Usage

```console
coder provisioner jobs cancel [flags] <job_id>
```

## Options

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder provisioner jobs list

Source: https://coder.com/docs/reference/cli/provisioner/jobs/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List provisioner jobs

Aliases:

* ls

## Usage

```console
coder provisioner jobs list [flags]
```

## Options

### -s, --status

|             |                                                                                  |
|-------------|----------------------------------------------------------------------------------|
| Type        | <code>[pending\|running\|succeeded\|canceling\|canceled\|failed\|unknown]</code> |
| Environment | <code>$CODER_PROVISIONER_JOB_LIST_STATUS</code>                                  |

Filter by job status.

### -l, --limit

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>int</code>                               |
| Environment | <code>$CODER_PROVISIONER_JOB_LIST_LIMIT</code> |
| Default     | <code>50</code>                                |

Limit the number of jobs returned.

### -i, --initiator

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>string</code>                                |
| Environment | <code>$CODER_PROVISIONER_JOB_LIST_INITIATOR</code> |

Filter by initiator (user ID or username).

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

### -c, --column

|         |                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[id\|created at\|started at\|completed at\|canceled at\|error\|error code\|status\|worker id\|worker name\|file id\|tags\|queue position\|queue size\|organization id\|initiator id\|template version id\|workspace build id\|type\|available workers\|template version name\|template id\|template name\|template display name\|template icon\|workspace id\|workspace name\|workspace build transition\|logs overflowed\|organization\|queue]</code> |
| Default | <code>created at,id,type,template display name,status,queue,tags</code>                                                                                                                                                                                                                                                                                                                                                                                      |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder provisioner keys

Source: https://coder.com/docs/reference/cli/provisioner/keys

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage provisioner keys

Aliases:

* key

## Usage

```console
coder provisioner keys
```

## Subcommands

| Name                               | Purpose                                  |
|------------------------------------|------------------------------------------|
| [<code>create</code>](./create.md) | Create a new provisioner key             |
| [<code>list</code>](./list.md)     | List provisioner keys in an organization |
| [<code>delete</code>](./delete.md) | Delete a provisioner key                 |

---

# coder provisioner keys create

Source: https://coder.com/docs/reference/cli/provisioner/keys/create

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create a new provisioner key

## Usage

```console
coder provisioner keys create [flags] <name>
```

## Options

### -t, --tag

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string-array</code>             |
| Environment | <code>$CODER_PROVISIONERD_TAGS</code> |

Tags to filter provisioner jobs by.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder provisioner keys delete

Source: https://coder.com/docs/reference/cli/provisioner/keys/delete

<!-- DO NOT EDIT | GENERATED CONTENT -->

Delete a provisioner key

Aliases:

* rm

## Usage

```console
coder provisioner keys delete [flags] <name>
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder provisioner keys list

Source: https://coder.com/docs/reference/cli/provisioner/keys/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List provisioner keys in an organization

Aliases:

* ls

## Usage

```console
coder provisioner keys list [flags]
```

## Options

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

### -c, --column

|         |                                       |
|---------|---------------------------------------|
| Type    | <code>[created at\|name\|tags]</code> |
| Default | <code>created at,name,tags</code>     |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder provisioner list

Source: https://coder.com/docs/reference/cli/provisioner/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List provisioner daemons in an organization

Aliases:

* ls

## Usage

```console
coder provisioner list [flags]
```

## Options

### -l, --limit

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>int</code>                           |
| Environment | <code>$CODER_PROVISIONER_LIST_LIMIT</code> |
| Default     | <code>50</code>                            |

Limit the number of provisioners returned.

### -f, --show-offline

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>bool</code>                            |
| Environment | <code>$CODER_PROVISIONER_SHOW_OFFLINE</code> |

Show offline provisioners.

### -s, --status

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>[offline\|idle\|busy]</code>          |
| Environment | <code>$CODER_PROVISIONER_LIST_STATUS</code> |

Filter by provisioner status.

### -m, --max-age

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>duration</code>                        |
| Environment | <code>$CODER_PROVISIONER_LIST_MAX_AGE</code> |

Filter provisioners by maximum age.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

### -c, --column

|         |                                                                                                                                                                                                                                                                                                                                                                                               |
|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Type    | <code>[id\|organization id\|created at\|last seen at\|name\|version\|api version\|tags\|key name\|status\|current job id\|current job status\|current job template name\|current job template icon\|current job template display name\|previous job id\|previous job status\|previous job template name\|previous job template icon\|previous job template display name\|organization]</code> |
| Default | <code>created at,last seen at,key name,name,version,status,tags</code>                                                                                                                                                                                                                                                                                                                        |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder provisioner start

Source: https://coder.com/docs/reference/cli/provisioner/start

<!-- DO NOT EDIT | GENERATED CONTENT -->

Run a provisioner daemon

## Usage

```console
coder provisioner start [flags]
```

## Options

### -c, --cache-dir

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string</code>                 |
| Environment | <code>$CODER_CACHE_DIRECTORY</code> |
| Default     | <code>~/.cache/coder</code>         |

Directory to store cached data.

### -t, --tag

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string-array</code>             |
| Environment | <code>$CODER_PROVISIONERD_TAGS</code> |

Tags to filter provisioner jobs by.

### --poll-interval

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>duration</code>                          |
| Environment | <code>$CODER_PROVISIONERD_POLL_INTERVAL</code> |
| Default     | <code>1s</code>                                |

Deprecated and ignored.

### --poll-jitter

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>duration</code>                        |
| Environment | <code>$CODER_PROVISIONERD_POLL_JITTER</code> |
| Default     | <code>100ms</code>                           |

Deprecated and ignored.

### --psk

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string</code>                        |
| Environment | <code>$CODER_PROVISIONER_DAEMON_PSK</code> |

Pre-shared key to authenticate with Coder server.

### --key

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string</code>                        |
| Environment | <code>$CODER_PROVISIONER_DAEMON_KEY</code> |

Provisioner key to authenticate with Coder server.

### --name

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_PROVISIONER_DAEMON_NAME</code> |

Name of this provisioner daemon. Defaults to the current hostname without FQDN.

### --verbose

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>bool</code>                              |
| Environment | <code>$CODER_PROVISIONER_DAEMON_VERBOSE</code> |
| Default     | <code>false</code>                             |

Output debug-level logs.

### --log-human

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>string</code>                                  |
| Environment | <code>$CODER_PROVISIONER_DAEMON_LOGGING_HUMAN</code> |
| Default     | <code>/dev/stderr</code>                             |

Output human-readable logs to a given file.

### --log-json

|             |                                                     |
|-------------|-----------------------------------------------------|
| Type        | <code>string</code>                                 |
| Environment | <code>$CODER_PROVISIONER_DAEMON_LOGGING_JSON</code> |

Output JSON logs to a given file.

### --log-stackdriver

|             |                                                            |
|-------------|------------------------------------------------------------|
| Type        | <code>string</code>                                        |
| Environment | <code>$CODER_PROVISIONER_DAEMON_LOGGING_STACKDRIVER</code> |

Output Stackdriver compatible logs to a given file.

### --log-filter

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>string-array</code>                         |
| Environment | <code>$CODER_PROVISIONER_DAEMON_LOG_FILTER</code> |

Filter debug logs by matching against a given regex. Use .* to match all debug logs.

### --prometheus-enable

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>bool</code>                     |
| Environment | <code>$CODER_PROMETHEUS_ENABLE</code> |
| Default     | <code>false</code>                    |

Serve prometheus metrics on the address defined by prometheus address.

### --prometheus-address

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string</code>                    |
| Environment | <code>$CODER_PROMETHEUS_ADDRESS</code> |
| Default     | <code>127.0.0.1:2112</code>            |

The bind address to serve prometheus metrics.

### --experiments

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>string-array</code>       |
| Environment | <code>$CODER_EXPERIMENTS</code> |
| YAML        | <code>experiments</code>        |

Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.

### -O, --org

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string</code>              |
| Environment | <code>$CODER_ORGANIZATION</code> |

Select which organization (uuid or name) to use.

---

# coder publickey

Source: https://coder.com/docs/reference/cli/publickey

<!-- DO NOT EDIT | GENERATED CONTENT -->

Output your Coder public key used for Git operations

Aliases:

* pubkey

## Usage

```console
coder publickey [flags]
```

## Options

### --reset

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Regenerate your public key. This will require updating the key on any services it's registered with.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder rename

Source: https://coder.com/docs/reference/cli/rename

<!-- DO NOT EDIT | GENERATED CONTENT -->

Rename a workspace

## Usage

```console
coder rename [flags] <workspace> <new name>
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder reset-password

Source: https://coder.com/docs/reference/cli/reset-password

<!-- DO NOT EDIT | GENERATED CONTENT -->

Directly connect to the database to reset a user's password

## Usage

```console
coder reset-password [flags] <username>
```

## Options

### --postgres-url

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string</code>                   |
| Environment | <code>$CODER_PG_CONNECTION_URL</code> |

URL of a PostgreSQL database to connect to.

### --postgres-connection-auth

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>password\|awsiamrds</code>       |
| Environment | <code>$CODER_PG_CONNECTION_AUTH</code> |
| Default     | <code>password</code>                  |

Type of auth to use when connecting to postgres.

---

# coder restart

Source: https://coder.com/docs/reference/cli/restart

<!-- DO NOT EDIT | GENERATED CONTENT -->

Restart a workspace

## Usage

```console
coder restart [flags] <workspace>
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

### --build-option

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>string-array</code>        |
| Environment | <code>$CODER_BUILD_OPTION</code> |

Build option value in the format "name=value".

### --build-options

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Prompt for one-time build options defined with ephemeral parameters.

### --ephemeral-parameter

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string-array</code>               |
| Environment | <code>$CODER_EPHEMERAL_PARAMETER</code> |

Set the value of ephemeral parameters defined in the template. The format is "name=value".

### --prompt-ephemeral-parameters

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>bool</code>                               |
| Environment | <code>$CODER_PROMPT_EPHEMERAL_PARAMETERS</code> |

Prompt to set values of ephemeral parameters defined in the template. If a value has been set via --ephemeral-parameter, it will not be prompted for.

### --parameter

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>string-array</code>          |
| Environment | <code>$CODER_RICH_PARAMETER</code> |

Rich parameter value in the format "name=value".

### --rich-parameter-file

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_RICH_PARAMETER_FILE</code> |

Specify a file path with values for rich parameters defined in the template. The file should be in YAML format, containing key-value pairs for the parameters.

### --parameter-default

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string-array</code>                  |
| Environment | <code>$CODER_RICH_PARAMETER_DEFAULT</code> |

Rich parameter default values in the format "name=value".

### --use-parameter-defaults

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>bool</code>                                    |
| Environment | <code>$CODER_WORKSPACE_USE_PARAMETER_DEFAULTS</code> |

Automatically accept parameter defaults when no value is provided.

### --always-prompt

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Always prompt all parameters. Does not pull parameter values from existing workspace.

---

# coder schedule

Source: https://coder.com/docs/reference/cli/schedule

<!-- DO NOT EDIT | GENERATED CONTENT -->

Schedule automated start and stop times for workspaces

## Usage

```console
coder schedule { show | start | stop | extend } <workspace>
```

## Subcommands

| Name                               | Purpose                                                         |
|------------------------------------|-----------------------------------------------------------------|
| [<code>show</code>](./show.md)     | Show workspace schedules                                        |
| [<code>start</code>](./start.md)   | Edit workspace start schedule                                   |
| [<code>stop</code>](./stop.md)     | Edit workspace stop schedule                                    |
| [<code>extend</code>](./extend.md) | Extend the stop time of a currently running workspace instance. |

---

# coder schedule extend

Source: https://coder.com/docs/reference/cli/schedule/extend

<!-- DO NOT EDIT | GENERATED CONTENT -->

Extend the stop time of a currently running workspace instance.

Aliases:

* override-stop

## Usage

```console
coder schedule extend <workspace-name> <duration from now>
```

## Description

```console
Extends the workspace deadline.
  * The new stop time is calculated from *now*.
  * The new stop time must be at least 30 minutes in the future.
  * The workspace template may restrict the maximum workspace runtime.

 $ coder schedule extend my-workspace 90m
```

---

# coder schedule show

Source: https://coder.com/docs/reference/cli/schedule/show

<!-- DO NOT EDIT | GENERATED CONTENT -->

Show workspace schedules

## Usage

```console
coder schedule show [flags] <workspace | --search <query> | --all>
```

## Description

```console
Shows the following information for the given workspace(s):
  * The automatic start schedule
  * The next scheduled start time
  * The duration after which it will stop
  * The next scheduled stop time

```

## Options

### -a, --all

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Specifies whether all workspaces will be listed or not.

### --search

|         |                      |
|---------|----------------------|
| Type    | <code>string</code>  |
| Default | <code>user:me</code> |

Search for a workspace with a query.

### -c, --column

|         |                                                                           |
|---------|---------------------------------------------------------------------------|
| Type    | <code>[workspace\|starts at\|starts next\|stops after\|stops next]</code> |
| Default | <code>workspace,starts at,starts next,stops after,stops next</code>       |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder schedule start

Source: https://coder.com/docs/reference/cli/schedule/start

<!-- DO NOT EDIT | GENERATED CONTENT -->

Edit workspace start schedule

## Usage

```console
coder schedule start <workspace-name> { <start-time> [day-of-week] [location] | manual }
```

## Description

```console
Schedules a workspace to regularly start at a specific time.
Schedule format: <start-time> [day-of-week] [location].
  * Start-time (required) is accepted either in 12-hour (hh:mm{am|pm}) format, or 24-hour format hh:mm.
  * Day-of-week (optional) allows specifying in the cron format, e.g. 1,3,5 or Mon-Fri.
    Aliases such as @daily are not supported.
    Default: * (every day)
  * Location (optional) must be a valid location in the IANA timezone database.
    If omitted, we will fall back to either the TZ environment variable or /etc/localtime.
    You can check your corresponding location by visiting https://ipinfo.io - it shows in the demo widget on the right.

  - Set the workspace to start at 9:30am (in Dublin) from Monday to Friday:

     $ coder schedule start my-workspace 9:30AM Mon-Fri Europe/Dublin
```

---

# coder schedule stop

Source: https://coder.com/docs/reference/cli/schedule/stop

<!-- DO NOT EDIT | GENERATED CONTENT -->

Edit workspace stop schedule

## Usage

```console
coder schedule stop <workspace-name> { <duration> | manual }
```

## Description

```console
Schedules a workspace to stop after a given duration has elapsed.
  * Workspace runtime is measured from the time that the workspace build completed.
  * The minimum scheduled stop time is 1 minute.
  * The workspace template may place restrictions on the maximum shutdown time.
  * Changes to workspace schedules only take effect upon the next build of the workspace,
    and do not affect a running instance of a workspace.

When enabling scheduled stop, enter a duration in one of the following formats:
  * 3h2m (3 hours and two minutes)
  * 3h   (3 hours)
  * 2m   (2 minutes)
  * 2    (2 minutes)

 $ coder schedule stop my-workspace 2h30m
```

---

# coder secret

Source: https://coder.com/docs/reference/cli/secret

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage secrets

Aliases:

* secrets

## Usage

```console
coder secret
```

## Description

```console
  - Create a secret:

     $ printf %s "$MYCLI_API_KEY" | coder secret create api-key --description "API key for workspace tools" --env API_KEY --file "~/.api-key"

  - Update a secret:

     $ echo -n "$NEW_SECRET_VALUE" | coder secret update api-key --description "Rotated API key" --env API_KEY --file "~/.api-key"

  - Import secrets from a file:

     $ coder secret import ./secrets.env

  - List your secrets:

     $ coder secret list

  - Show a specific secret:

     $ coder secret list api-key

  - Delete a secret:

     $ coder secret delete api-key
```

## Subcommands

| Name                                 | Purpose                                           |
|--------------------------------------|---------------------------------------------------|
| [<code>create</code>](./create.md)   | Create a secret                                   |
| [<code>update</code>](./update.md)   | Update a secret                                   |
| [<code>import</code>](./import.md)   | Import secrets from a file                        |
| [<code>enable</code>](./enable.md)   | Enable a secret so it is injected into workspaces |
| [<code>disable</code>](./disable.md) | Disable a secret without removing it              |
| [<code>list</code>](./list.md)       | List secrets, or show one by name                 |
| [<code>delete</code>](./delete.md)   | Delete a secret                                   |

---

# coder secret create

Source: https://coder.com/docs/reference/cli/secret/create

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create a secret

## Usage

```console
coder secret create [flags] <name>
```

## Description

```console
Provide the secret value with --value or non-interactive stdin (pipe or redirect).
```

## Options

### --value

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Set the secret value. For security reasons, prefer non-interactive stdin (pipe or redirect).

### --description

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Set the secret description.

### --env

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Name of the workspace environment variable that this secret will set.

### --file

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Workspace file path where this secret will be written. Must start with ~/ or /.

### --enabled

|         |                   |
|---------|-------------------|
| Type    | <code>bool</code> |
| Default | <code>true</code> |

Whether the secret is injected into workspaces. An enabled secret must set --env or --file; pass --enabled=false to store a secret without injecting it.

---

# coder secret delete

Source: https://coder.com/docs/reference/cli/secret/delete

<!-- DO NOT EDIT | GENERATED CONTENT -->

Delete a secret

Aliases:

* remove
* rm

## Usage

```console
coder secret delete [flags] <name>
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder secret disable

Source: https://coder.com/docs/reference/cli/secret/disable

<!-- DO NOT EDIT | GENERATED CONTENT -->

Disable a secret without removing it

## Usage

```console
coder secret disable <name>
```

---

# coder secret enable

Source: https://coder.com/docs/reference/cli/secret/enable

<!-- DO NOT EDIT | GENERATED CONTENT -->

Enable a secret so it is injected into workspaces

## Usage

```console
coder secret enable <name>
```

---

# coder secret import

Source: https://coder.com/docs/reference/cli/secret/import

<!-- DO NOT EDIT | GENERATED CONTENT -->

Import secrets from a file

## Usage

```console
coder secret import [flags] <file>
```

## Description

```console
Every key in the file becomes a secret. Keys allowed as environment variable names are injected into workspaces under the same name. The import is all or nothing, and existing secrets are never overwritten. Pass - to read the file from non-interactive stdin (pipe or redirect).
```

## Options

### --input-format

|      |                              |
|------|------------------------------|
| Type | <code>env\|json\|yaml</code> |

Format of the secrets file. Inferred from the file extension when unset, and required when reading from stdin.

---

# coder secret list

Source: https://coder.com/docs/reference/cli/secret/list

<!-- DO NOT EDIT | GENERATED CONTENT -->

List secrets, or show one by name

Aliases:

* ls

## Usage

```console
coder secret list [flags] [name]
```

## Description

```console
Secret values are omitted from the output.
```

## Options

### -c, --column

|         |                                                                        |
|---------|------------------------------------------------------------------------|
| Type    | <code>[created\|name\|updated\|env\|file\|enabled\|description]</code> |
| Default | <code>name,created,updated,env,file,enabled,description</code>         |

Columns to display in table output.

### -o, --output

|         |                          |
|---------|--------------------------|
| Type    | <code>table\|json</code> |
| Default | <code>table</code>       |

Output format.

---

# coder secret update

Source: https://coder.com/docs/reference/cli/secret/update

<!-- DO NOT EDIT | GENERATED CONTENT -->

Update a secret

## Usage

```console
coder secret update [flags] <name>
```

## Description

```console
At least one of --value, --description, --env, --file, or --enabled must be specified. Provide the secret value by at most one of --value or non-interactive stdin (pipe or redirect).
```

## Options

### --value

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Update the secret value. For security reasons, prefer non-interactive stdin (pipe or redirect).

### --description

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Update the secret description. Pass an empty string to clear it.

### --env

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Name of the workspace environment variable that this secret will set. Pass an empty string to clear it.

### --file

|      |                     |
|------|---------------------|
| Type | <code>string</code> |

Workspace file path where this secret will be written. Must start with ~/ or /. Pass an empty string to clear it.

### --enabled

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Whether the secret is injected into workspaces. An enabled secret must keep at least one of --env or --file; pass --enabled=false to stop injecting it without deleting it.

---

# coder server

Source: https://coder.com/docs/reference/cli/server

<!-- DO NOT EDIT | GENERATED CONTENT -->

Start a Coder server

## Usage

```console
coder server [flags]
```

## Subcommands

| Name                                                               | Purpose                                                                                                |
|--------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
| [<code>create-admin-user</code>](./create-admin-user.md)           | Create a new admin user with the given username, email and password and adds it to every organization. |
| [<code>postgres-builtin-url</code>](./postgres-builtin-url.md)     | Output the connection URL for the built-in PostgreSQL deployment.                                      |
| [<code>postgres-builtin-serve</code>](./postgres-builtin-serve.md) | Run the built-in PostgreSQL deployment.                                                                |
| [<code>fix-oidc-links</code>](./fix-oidc-links.md)                 | Reset OIDC linked IDs that do not match the expected issuer, allowing users to re-authenticate.        |
| [<code>dbcrypt</code>](./dbcrypt/index.md)                         | Manage database encryption.                                                                            |

## Options

### --mcp-allowed-private-cidrs

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>string-array</code>                     |
| Environment | <code>$CODER_MCP_ALLOWED_PRIVATE_CIDRS</code> |
| YAML        | <code>mcp.allowed_private_cidrs</code>        |

MCP server destinations in private or reserved IP ranges are blocked by default for SSRF protection. This applies to OAuth2 discovery, OAuth2 token and revocation exchanges, and runtime MCP connections from coderd. This option exempts specific CIDRs.

### --access-url

|             |                                   |
|-------------|-----------------------------------|
| Type        | <code>url</code>                  |
| Environment | <code>$CODER_ACCESS_URL</code>    |
| YAML        | <code>networking.accessURL</code> |

The URL that users will use to access the Coder deployment.

### --wildcard-access-url

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>string</code>                       |
| Environment | <code>$CODER_WILDCARD_ACCESS_URL</code>   |
| YAML        | <code>networking.wildcardAccessURL</code> |

Specifies the wildcard hostname to use for workspace applications in the form "*.example.com".

### --docs-url

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>url</code>                    |
| Environment | <code>$CODER_DOCS_URL</code>        |
| YAML        | <code>networking.docsURL</code>     |
| Default     | <code>https://coder.com/docs</code> |

Specifies the custom docs URL.

### --redirect-to-access-url

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>bool</code>                           |
| Environment | <code>$CODER_REDIRECT_TO_ACCESS_URL</code>  |
| YAML        | <code>networking.redirectToAccessURL</code> |

Specifies whether to redirect requests that do not match the access URL host.

### --http-address

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_HTTP_ADDRESS</code>         |
| YAML        | <code>networking.http.httpAddress</code> |
| Default     | <code>127.0.0.1:3000</code>              |

HTTP bind address of the server. Unset to disable the HTTP endpoint.

### --tls-address

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>host:port</code>              |
| Environment | <code>$CODER_TLS_ADDRESS</code>     |
| YAML        | <code>networking.tls.address</code> |
| Default     | <code>127.0.0.1:3443</code>         |

HTTPS bind address of the server.

### --tls-enable

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>bool</code>                  |
| Environment | <code>$CODER_TLS_ENABLE</code>     |
| YAML        | <code>networking.tls.enable</code> |

Whether TLS will be enabled.

### --tls-cert-file

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string-array</code>             |
| Environment | <code>$CODER_TLS_CERT_FILE</code>     |
| YAML        | <code>networking.tls.certFiles</code> |

Path to each certificate for TLS. It requires a PEM-encoded file. To configure the listener to use a CA certificate, concatenate the primary certificate and the CA certificate together. The primary certificate should appear first in the combined file.

### --tls-client-ca-file

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_TLS_CLIENT_CA_FILE</code>   |
| YAML        | <code>networking.tls.clientCAFile</code> |

PEM-encoded Certificate Authority file used for checking the authenticity of client.

### --tls-client-auth

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string</code>                    |
| Environment | <code>$CODER_TLS_CLIENT_AUTH</code>    |
| YAML        | <code>networking.tls.clientAuth</code> |
| Default     | <code>none</code>                      |

Policy the server will follow for TLS Client Authentication. Accepted values are "none", "request", "require-any", "verify-if-given", or "require-and-verify".

### --tls-key-file

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string-array</code>            |
| Environment | <code>$CODER_TLS_KEY_FILE</code>     |
| YAML        | <code>networking.tls.keyFiles</code> |

Paths to the private keys for each of the certificates. It requires a PEM-encoded file.

### --tls-min-version

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string</code>                    |
| Environment | <code>$CODER_TLS_MIN_VERSION</code>    |
| YAML        | <code>networking.tls.minVersion</code> |
| Default     | <code>tls12</code>                     |

Minimum supported version of TLS. Accepted values are "tls10", "tls11", "tls12" or "tls13".

### --tls-client-cert-file

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string</code>                        |
| Environment | <code>$CODER_TLS_CLIENT_CERT_FILE</code>   |
| YAML        | <code>networking.tls.clientCertFile</code> |

Path to certificate for client TLS authentication. It requires a PEM-encoded file.

### --tls-client-key-file

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>string</code>                       |
| Environment | <code>$CODER_TLS_CLIENT_KEY_FILE</code>   |
| YAML        | <code>networking.tls.clientKeyFile</code> |

Path to key for client TLS authentication. It requires a PEM-encoded file.

### --tls-ciphers

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string-array</code>              |
| Environment | <code>$CODER_TLS_CIPHERS</code>        |
| YAML        | <code>networking.tls.tlsCiphers</code> |

Specify specific TLS ciphers that allowed to be used. See https://github.com/golang/go/blob/master/src/crypto/tls/cipher_suites.go#L53-L75.

### --tls-allow-insecure-ciphers

|             |                                                     |
|-------------|-----------------------------------------------------|
| Type        | <code>bool</code>                                   |
| Environment | <code>$CODER_TLS_ALLOW_INSECURE_CIPHERS</code>      |
| YAML        | <code>networking.tls.tlsAllowInsecureCiphers</code> |
| Default     | <code>false</code>                                  |

By default, only ciphers marked as 'secure' are allowed to be used. See https://github.com/golang/go/blob/master/src/crypto/tls/cipher_suites.go#L82-L95.

### --derp-server-enable

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>bool</code>                      |
| Environment | <code>$CODER_DERP_SERVER_ENABLE</code> |
| YAML        | <code>networking.derp.enable</code>    |
| Default     | <code>true</code>                      |

Whether to enable or disable the embedded DERP relay server.

### --derp-server-region-name

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_DERP_SERVER_REGION_NAME</code> |
| YAML        | <code>networking.derp.regionName</code>     |
| Default     | <code>Coder Embedded Relay</code>           |

Region name that for the embedded DERP server.

### --derp-server-stun-addresses

|             |                                                                                                                                          |
|-------------|------------------------------------------------------------------------------------------------------------------------------------------|
| Type        | <code>string-array</code>                                                                                                                |
| Environment | <code>$CODER_DERP_SERVER_STUN_ADDRESSES</code>                                                                                           |
| YAML        | <code>networking.derp.stunAddresses</code>                                                                                               |
| Default     | <code>stun.l.google.com:19302,stun1.l.google.com:19302,stun2.l.google.com:19302,stun3.l.google.com:19302,stun4.l.google.com:19302</code> |

Addresses for STUN servers to establish P2P connections. It's recommended to have at least two STUN servers to give users the best chance of connecting P2P to workspaces. Each STUN server will get it's own DERP region, with region IDs starting at `--derp-server-region-id + 1`. Use special value 'disable' to turn off STUN completely.

### --derp-server-relay-url

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>url</code>                          |
| Environment | <code>$CODER_DERP_SERVER_RELAY_URL</code> |
| YAML        | <code>networking.derp.relayURL</code>     |

An HTTP URL that is accessible by other replicas to relay DERP traffic. Required for high availability.

### --block-direct-connections

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>bool</code>                        |
| Environment | <code>$CODER_BLOCK_DIRECT</code>         |
| YAML        | <code>networking.derp.blockDirect</code> |

Block peer-to-peer (aka. direct) workspace connections. All workspace connections from the CLI will be proxied through Coder (or custom configured DERP servers) and will never be peer-to-peer when enabled. Workspaces may still reach out to STUN servers to get their address until they are restarted after this change has been made, but new connections will still be proxied regardless.

### --derp-force-websockets

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>bool</code>                            |
| Environment | <code>$CODER_DERP_FORCE_WEBSOCKETS</code>    |
| YAML        | <code>networking.derp.forceWebSockets</code> |

Force clients and agents to always use WebSocket to connect to DERP relay servers. By default, DERP uses `Upgrade: derp`, which may cause issues with some reverse proxies. Clients may automatically fallback to WebSocket if they detect an issue with `Upgrade: derp`, but this does not work in all situations.

### --derp-config-url

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string</code>                 |
| Environment | <code>$CODER_DERP_CONFIG_URL</code> |
| YAML        | <code>networking.derp.url</code>    |

URL to fetch a DERP mapping on startup. See: https://tailscale.com/kb/1118/custom-derp-servers/.

### --derp-config-path

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_DERP_CONFIG_PATH</code>    |
| YAML        | <code>networking.derp.configPath</code> |

Path to read a DERP mapping from. See: https://tailscale.com/kb/1118/custom-derp-servers/.

### --stats-collection-usage-stats-enable

|             |                                                              |
|-------------|--------------------------------------------------------------|
| Type        | <code>bool</code>                                            |
| Environment | <code>$CODER_STATS_COLLECTION_USAGE_STATS_ENABLE</code>      |
| YAML        | <code>introspection.statsCollection.usageStats.enable</code> |
| Default     | <code>true</code>                                            |

Enable the collection of application and workspace usage along with the associated API endpoints and the template insights page. Disabling this will also disable traffic and connection insights in the deployment stats shown to admins in the bottom bar of the Coder UI, and will prevent Prometheus collection of these values.

### --prometheus-enable

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>bool</code>                            |
| Environment | <code>$CODER_PROMETHEUS_ENABLE</code>        |
| YAML        | <code>introspection.prometheus.enable</code> |

Serve prometheus metrics on the address defined by prometheus address.

### --prometheus-address

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>host:port</code>                        |
| Environment | <code>$CODER_PROMETHEUS_ADDRESS</code>        |
| YAML        | <code>introspection.prometheus.address</code> |
| Default     | <code>127.0.0.1:2112</code>                   |

The bind address to serve prometheus metrics.

### --prometheus-collect-agent-stats

|             |                                                           |
|-------------|-----------------------------------------------------------|
| Type        | <code>bool</code>                                         |
| Environment | <code>$CODER_PROMETHEUS_COLLECT_AGENT_STATS</code>        |
| YAML        | <code>introspection.prometheus.collect_agent_stats</code> |

Collect agent stats (may increase charges for metrics storage).

### --prometheus-aggregate-agent-stats-by

|             |                                                                |
|-------------|----------------------------------------------------------------|
| Type        | <code>string-array</code>                                      |
| Environment | <code>$CODER_PROMETHEUS_AGGREGATE_AGENT_STATS_BY</code>        |
| YAML        | <code>introspection.prometheus.aggregate_agent_stats_by</code> |
| Default     | <code>agent_name,template_name,username,workspace_name</code>  |

When collecting agent stats, aggregate metrics by a given set of comma-separated labels to reduce cardinality. Accepted values are agent_name, template_name, username, workspace_name.

### --prometheus-collect-db-metrics

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>bool</code>                                        |
| Environment | <code>$CODER_PROMETHEUS_COLLECT_DB_METRICS</code>        |
| YAML        | <code>introspection.prometheus.collect_db_metrics</code> |
| Default     | <code>false</code>                                       |

Collect database query metrics (may increase charges for metrics storage). If set to false, a reduced set of database metrics are still collected.

### --pprof-enable

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>bool</code>                       |
| Environment | <code>$CODER_PPROF_ENABLE</code>        |
| YAML        | <code>introspection.pprof.enable</code> |

Serve pprof metrics on the address defined by pprof address.

### --pprof-address

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>host:port</code>                   |
| Environment | <code>$CODER_PPROF_ADDRESS</code>        |
| YAML        | <code>introspection.pprof.address</code> |
| Default     | <code>127.0.0.1:6060</code>              |

The bind address to serve pprof.

### --oauth2-github-client-id

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_OAUTH2_GITHUB_CLIENT_ID</code> |
| YAML        | <code>oauth2.github.clientID</code>         |

Client ID for Login with GitHub.

### --oauth2-github-client-secret

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>string</code>                             |
| Environment | <code>$CODER_OAUTH2_GITHUB_CLIENT_SECRET</code> |

Client secret for Login with GitHub.

### --oauth2-github-device-flow

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>bool</code>                             |
| Environment | <code>$CODER_OAUTH2_GITHUB_DEVICE_FLOW</code> |
| YAML        | <code>oauth2.github.deviceFlow</code>         |
| Default     | <code>false</code>                            |

Enable device flow for Login with GitHub.

### --oauth2-github-default-provider-enable

|             |                                                           |
|-------------|-----------------------------------------------------------|
| Type        | <code>bool</code>                                         |
| Environment | <code>$CODER_OAUTH2_GITHUB_DEFAULT_PROVIDER_ENABLE</code> |
| YAML        | <code>oauth2.github.defaultProviderEnable</code>          |
| Default     | <code>true</code>                                         |

Enable the default GitHub OAuth2 provider managed by Coder.

### --oauth2-github-allowed-orgs

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>string-array</code>                      |
| Environment | <code>$CODER_OAUTH2_GITHUB_ALLOWED_ORGS</code> |
| YAML        | <code>oauth2.github.allowedOrgs</code>         |

Organizations the user must be a member of to Login with GitHub.

### --oauth2-github-allowed-teams

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>string-array</code>                       |
| Environment | <code>$CODER_OAUTH2_GITHUB_ALLOWED_TEAMS</code> |
| YAML        | <code>oauth2.github.allowedTeams</code>         |

Teams inside organizations the user must be a member of to Login with GitHub. Structured as: `<organization-name>/<team-slug>`.

### --oauth2-github-allow-signups

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>bool</code>                               |
| Environment | <code>$CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS</code> |
| YAML        | <code>oauth2.github.allowSignups</code>         |

Whether new users can sign up with GitHub.

### --oauth2-github-allow-everyone

|             |                                                  |
|-------------|--------------------------------------------------|
| Type        | <code>bool</code>                                |
| Environment | <code>$CODER_OAUTH2_GITHUB_ALLOW_EVERYONE</code> |
| YAML        | <code>oauth2.github.allowEveryone</code>         |

Allow all logins, setting this option means allowed orgs and teams must be empty.

### --oauth2-github-enterprise-base-url

|             |                                                       |
|-------------|-------------------------------------------------------|
| Type        | <code>string</code>                                   |
| Environment | <code>$CODER_OAUTH2_GITHUB_ENTERPRISE_BASE_URL</code> |
| YAML        | <code>oauth2.github.enterpriseBaseURL</code>          |

Base URL of a GitHub Enterprise deployment to use for Login with GitHub.

### --oauth2-provider-enable

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>bool</code>                          |
| Environment | <code>$CODER_OAUTH2_PROVIDER_ENABLE</code> |
| YAML        | <code>oauth2.provider.enable</code>        |
| Default     | <code>false</code>                         |

Enable the OAuth 2.1 authorization server, which lets external applications (such as MCP clients) obtain tokens for Coder on behalf of users. Disabled by default. When disabled, the OAuth2 endpoints and discovery documents return 404.

### --oidc-allow-signups

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>bool</code>                      |
| Environment | <code>$CODER_OIDC_ALLOW_SIGNUPS</code> |
| YAML        | <code>oidc.allowSignups</code>         |
| Default     | <code>true</code>                      |

Whether new users can sign up with OIDC.

### --oidc-client-id

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>string</code>                |
| Environment | <code>$CODER_OIDC_CLIENT_ID</code> |
| YAML        | <code>oidc.clientID</code>         |

Client ID to use for Login with OIDC.

### --oidc-client-secret

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string</code>                    |
| Environment | <code>$CODER_OIDC_CLIENT_SECRET</code> |

Client secret to use for Login with OIDC.

### --oidc-client-key-file

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_OIDC_CLIENT_KEY_FILE</code> |
| YAML        | <code>oidc.oidcClientKeyFile</code>      |

Pem encoded RSA private key to use for oauth2 PKI/JWT authorization. This can be used instead of oidc-client-secret if your IDP supports it.

### --oidc-client-cert-file

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>string</code>                       |
| Environment | <code>$CODER_OIDC_CLIENT_CERT_FILE</code> |
| YAML        | <code>oidc.oidcClientCertFile</code>      |

Pem encoded certificate file to use for oauth2 PKI/JWT authorization. The public certificate that accompanies oidc-client-key-file. A standard x509 certificate is expected.

### --oidc-email-domain

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string-array</code>             |
| Environment | <code>$CODER_OIDC_EMAIL_DOMAIN</code> |
| YAML        | <code>oidc.emailDomain</code>         |

Email domains that clients logging in with OIDC must match.

### --oidc-issuer-url

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string</code>                 |
| Environment | <code>$CODER_OIDC_ISSUER_URL</code> |
| YAML        | <code>oidc.issuerURL</code>         |

Issuer URL to use for Login with OIDC.

### --oidc-scopes

|             |                                   |
|-------------|-----------------------------------|
| Type        | <code>string-array</code>         |
| Environment | <code>$CODER_OIDC_SCOPES</code>   |
| YAML        | <code>oidc.scopes</code>          |
| Default     | <code>openid,profile,email</code> |

Scopes to grant when authenticating with OIDC.

### --oidc-ignore-email-verified

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>bool</code>                              |
| Environment | <code>$CODER_OIDC_IGNORE_EMAIL_VERIFIED</code> |
| YAML        | <code>oidc.ignoreEmailVerified</code>          |

Ignore the email_verified claim from the upstream provider.

### --oidc-username-field

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_OIDC_USERNAME_FIELD</code> |
| YAML        | <code>oidc.usernameField</code>         |
| Default     | <code>preferred_username</code>         |

OIDC claim field to use as the username.

### --oidc-name-field

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string</code>                 |
| Environment | <code>$CODER_OIDC_NAME_FIELD</code> |
| YAML        | <code>oidc.nameField</code>         |
| Default     | <code>name</code>                   |

OIDC claim field to use as the name.

### --oidc-email-field

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string</code>                  |
| Environment | <code>$CODER_OIDC_EMAIL_FIELD</code> |
| YAML        | <code>oidc.emailField</code>         |
| Default     | <code>email</code>                   |

OIDC claim field to use as the email.

### --oidc-auth-url-params

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>struct[map[string]string]</code>   |
| Environment | <code>$CODER_OIDC_AUTH_URL_PARAMS</code> |
| YAML        | <code>oidc.authURLParams</code>          |
| Default     | <code>{"access_type": "offline"}</code>  |

OIDC auth URL parameters to pass to the upstream provider.

### --oidc-ignore-userinfo

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>bool</code>                        |
| Environment | <code>$CODER_OIDC_IGNORE_USERINFO</code> |
| YAML        | <code>oidc.ignoreUserInfo</code>         |
| Default     | <code>false</code>                       |

Ignore the userinfo endpoint and only use the ID token for user information.

### --oidc-group-field

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string</code>                  |
| Environment | <code>$CODER_OIDC_GROUP_FIELD</code> |
| YAML        | <code>oidc.groupField</code>         |

This field must be set if using the group sync feature and the scope name is not 'groups'. Set to the claim to be used for groups.

### --oidc-group-mapping

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>struct[map[string]string]</code> |
| Environment | <code>$CODER_OIDC_GROUP_MAPPING</code> |
| YAML        | <code>oidc.groupMapping</code>         |
| Default     | <code>{}</code>                        |

A map of OIDC group IDs and the group in Coder it should map to. This is useful for when OIDC providers only return group IDs.

### --oidc-group-auto-create

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>bool</code>                          |
| Environment | <code>$CODER_OIDC_GROUP_AUTO_CREATE</code> |
| YAML        | <code>oidc.enableGroupAutoCreate</code>    |
| Default     | <code>false</code>                         |

Automatically creates missing groups from a user's groups claim.

### --oidc-group-regex-filter

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>regexp</code>                         |
| Environment | <code>$CODER_OIDC_GROUP_REGEX_FILTER</code> |
| YAML        | <code>oidc.groupRegexFilter</code>          |
| Default     | <code>.*</code>                             |

If provided any group name not matching the regex is ignored. This allows for filtering out groups that are not needed. This filter is applied after the group mapping.

### --oidc-allowed-groups

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string-array</code>               |
| Environment | <code>$CODER_OIDC_ALLOWED_GROUPS</code> |
| YAML        | <code>oidc.groupAllowed</code>          |

If provided any group name not in the list will not be allowed to authenticate. This allows for restricting access to a specific set of groups. This filter is applied after the group mapping and before the regex filter.

### --oidc-user-role-field

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_OIDC_USER_ROLE_FIELD</code> |
| YAML        | <code>oidc.userRoleField</code>          |

This field must be set if using the user roles sync feature. Set this to the name of the claim used to store the user's role. The roles should be sent as an array of strings.

### --oidc-user-role-mapping

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>struct[map[string][]string]</code>   |
| Environment | <code>$CODER_OIDC_USER_ROLE_MAPPING</code> |
| YAML        | <code>oidc.userRoleMapping</code>          |
| Default     | <code>{}</code>                            |

A map of the OIDC passed in user roles and the groups in Coder it should map to. This is useful if the group names do not match. If mapped to the empty string, the role will ignored.

### --oidc-user-role-default

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string-array</code>                  |
| Environment | <code>$CODER_OIDC_USER_ROLE_DEFAULT</code> |
| YAML        | <code>oidc.userRoleDefault</code>          |

If user role sync is enabled, these roles are always included for all authenticated users. The 'member' role is always assigned.

### --oidc-sign-in-text

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string</code>                   |
| Environment | <code>$CODER_OIDC_SIGN_IN_TEXT</code> |
| YAML        | <code>oidc.signInText</code>          |
| Default     | <code>OpenID Connect</code>           |

The text to show on the OpenID Connect sign in button.

### --oidc-icon-url

|             |                                   |
|-------------|-----------------------------------|
| Type        | <code>url</code>                  |
| Environment | <code>$CODER_OIDC_ICON_URL</code> |
| YAML        | <code>oidc.iconURL</code>         |

URL pointing to the icon to use on the OpenID Connect login button.

### --oidc-signups-disabled-text

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>string</code>                            |
| Environment | <code>$CODER_OIDC_SIGNUPS_DISABLED_TEXT</code> |
| YAML        | <code>oidc.signupsDisabledText</code>          |

The custom text to show on the error page informing about disabled OIDC signups. Markdown format is supported.

### --dangerous-oidc-skip-issuer-checks

|             |                                                       |
|-------------|-------------------------------------------------------|
| Type        | <code>bool</code>                                     |
| Environment | <code>$CODER_DANGEROUS_OIDC_SKIP_ISSUER_CHECKS</code> |
| YAML        | <code>oidc.dangerousSkipIssuerChecks</code>           |

OIDC issuer urls must match in the request, the id_token 'iss' claim, and in the well-known configuration. This flag disables that requirement, and can lead to an insecure OIDC configuration. It is not recommended to use this flag.

### --oidc-redirect-url

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>url</code>                      |
| Environment | <code>$CODER_OIDC_REDIRECT_URL</code> |
| YAML        | <code>oidc.oidc-redirect-url</code>   |

Optional override of the default redirect url which uses the deployment's access url. Useful in situations where a deployment has more than 1 domain. Using this setting can also break OIDC, so use with caution.

### --telemetry

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>bool</code>                    |
| Environment | <code>$CODER_TELEMETRY_ENABLE</code> |
| YAML        | <code>telemetry.enable</code>        |
| Default     | <code>true</code>                    |

Whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.

### --trace

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>bool</code>                         |
| Environment | <code>$CODER_TRACE_ENABLE</code>          |
| YAML        | <code>introspection.tracing.enable</code> |

Whether application tracing data is collected. It exports to a backend configured by environment variables. See: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md.

### --trace-honeycomb-api-key

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_TRACE_HONEYCOMB_API_KEY</code> |

Enables trace exporting to Honeycomb.io using the provided API Key.

### --trace-logs

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>bool</code>                              |
| Environment | <code>$CODER_TRACE_LOGS</code>                 |
| YAML        | <code>introspection.tracing.captureLogs</code> |

Enables capturing of logs as events in traces. This is useful for debugging, but may result in a very large amount of events being sent to the tracing backend which may incur significant costs.

### --provisioner-daemons

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>int</code>                        |
| Environment | <code>$CODER_PROVISIONER_DAEMONS</code> |
| YAML        | <code>provisioning.daemons</code>       |
| Default     | <code>3</code>                          |

Number of provisioner daemons to create on start. If builds are stuck in queued state for a long time, consider increasing this.

### --provisioner-daemon-poll-interval

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>duration</code>                                |
| Environment | <code>$CODER_PROVISIONER_DAEMON_POLL_INTERVAL</code> |
| YAML        | <code>provisioning.daemonPollInterval</code>         |
| Default     | <code>1s</code>                                      |

Deprecated and ignored.

### --provisioner-daemon-poll-jitter

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>duration</code>                              |
| Environment | <code>$CODER_PROVISIONER_DAEMON_POLL_JITTER</code> |
| YAML        | <code>provisioning.daemonPollJitter</code>         |
| Default     | <code>100ms</code>                                 |

Deprecated and ignored.

### --provisioner-force-cancel-interval

|             |                                                       |
|-------------|-------------------------------------------------------|
| Type        | <code>duration</code>                                 |
| Environment | <code>$CODER_PROVISIONER_FORCE_CANCEL_INTERVAL</code> |
| YAML        | <code>provisioning.forceCancelInterval</code>         |
| Default     | <code>10m0s</code>                                    |

Time to force cancel provisioning tasks that are stuck.

### --provisioner-disable-module-cache

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>bool</code>                                    |
| Environment | <code>$CODER_PROVISIONER_DISABLE_MODULE_CACHE</code> |
| YAML        | <code>provisioning.disableModuleCache</code>         |
| Default     | <code>false</code>                                   |

Disable the reuse of Terraform modules cached at template import for all templates. Modules are re-downloaded on every workspace build. Individual templates cannot opt back in.

### --provisioner-daemon-psk

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>string</code>                        |
| Environment | <code>$CODER_PROVISIONER_DAEMON_PSK</code> |

Pre-shared key to authenticate external provisioner daemons to Coder server.

### -l, --log-filter

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>string-array</code>                 |
| Environment | <code>$CODER_LOG_FILTER</code>            |
| YAML        | <code>introspection.logging.filter</code> |

Filter debug logs by matching against a given regex. Use .* to match all debug logs.

### --log-human

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>string</code>                          |
| Environment | <code>$CODER_LOGGING_HUMAN</code>            |
| YAML        | <code>introspection.logging.humanPath</code> |
| Default     | <code>/dev/stderr</code>                     |

Output human-readable logs to a given file.

### --log-json

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_LOGGING_JSON</code>            |
| YAML        | <code>introspection.logging.jsonPath</code> |

Output JSON logs to a given file.

### --log-stackdriver

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>string</code>                                |
| Environment | <code>$CODER_LOGGING_STACKDRIVER</code>            |
| YAML        | <code>introspection.logging.stackdriverPath</code> |

Output Stackdriver compatible logs to a given file.

### --enable-terraform-debug-mode

|             |                                                             |
|-------------|-------------------------------------------------------------|
| Type        | <code>bool</code>                                           |
| Environment | <code>$CODER_ENABLE_TERRAFORM_DEBUG_MODE</code>             |
| YAML        | <code>introspection.logging.enableTerraformDebugMode</code> |
| Default     | <code>false</code>                                          |

Allow administrators to enable Terraform debug output.

### --additional-csp-policy

|             |                                                  |
|-------------|--------------------------------------------------|
| Type        | <code>string-array</code>                        |
| Environment | <code>$CODER_ADDITIONAL_CSP_POLICY</code>        |
| YAML        | <code>networking.http.additionalCSPPolicy</code> |

Coder configures a Content Security Policy (CSP) to protect against XSS attacks. This setting allows you to add additional CSP directives, which can open the attack surface of the deployment. Format matches the CSP directive format, e.g. --additional-csp-policy="script-src https://example.com".

### --dangerous-allow-path-app-sharing

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>bool</code>                                    |
| Environment | <code>$CODER_DANGEROUS_ALLOW_PATH_APP_SHARING</code> |

Allow workspace apps that are not served from subdomains to be shared. Path-based app sharing is DISABLED by default for security purposes. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.

### --dangerous-allow-path-app-site-owner-access

|             |                                                                |
|-------------|----------------------------------------------------------------|
| Type        | <code>bool</code>                                              |
| Environment | <code>$CODER_DANGEROUS_ALLOW_PATH_APP_SITE_OWNER_ACCESS</code> |

Allow site-owners to access workspace apps from workspaces they do not own. Owners cannot access path-based apps they do not own by default. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. Path-based apps can be disabled entirely with --disable-path-apps for further security.

### --experiments

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>string-array</code>       |
| Environment | <code>$CODER_EXPERIMENTS</code> |
| YAML        | <code>experiments</code>        |

Enable one or more experiments. These are not ready for production. Separate multiple experiments with commas, or enter '*' to opt-in to all available experiments.

### --update-check

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>bool</code>                |
| Environment | <code>$CODER_UPDATE_CHECK</code> |
| YAML        | <code>updateCheck</code>         |
| Default     | <code>false</code>               |

Periodically check for new releases of Coder and inform the owner. The check is performed once per day.

### --max-token-lifetime

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>duration</code>                         |
| Environment | <code>$CODER_MAX_TOKEN_LIFETIME</code>        |
| YAML        | <code>networking.http.maxTokenLifetime</code> |
| Default     | <code>876600h0m0s</code>                      |

The maximum lifetime duration users can specify when creating an API token.

### --max-admin-token-lifetime

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>duration</code>                              |
| Environment | <code>$CODER_MAX_ADMIN_TOKEN_LIFETIME</code>       |
| YAML        | <code>networking.http.maxAdminTokenLifetime</code> |
| Default     | <code>168h0m0s</code>                              |

The maximum lifetime duration administrators can specify when creating an API token.

### --default-token-lifetime

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>duration</code>                      |
| Environment | <code>$CODER_DEFAULT_TOKEN_LIFETIME</code> |
| YAML        | <code>defaultTokenLifetime</code>          |
| Default     | <code>168h0m0s</code>                      |

The default lifetime duration for API tokens. This value is used when creating a token without specifying a duration, such as when authenticating the CLI or an IDE plugin.

### --default-oauth-refresh-lifetime

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>duration</code>                              |
| Environment | <code>$CODER_DEFAULT_OAUTH_REFRESH_LIFETIME</code> |
| YAML        | <code>defaultOAuthRefreshLifetime</code>           |
| Default     | <code>720h0m0s</code>                              |

The default lifetime duration for OAuth2 refresh tokens. This controls how long refresh tokens remain valid after issuance or rotation.

### --swagger-enable

|             |                                    |
|-------------|------------------------------------|
| Type        | <code>bool</code>                  |
| Environment | <code>$CODER_SWAGGER_ENABLE</code> |
| YAML        | <code>enableSwagger</code>         |

Expose the swagger endpoint via /swagger.

### --proxy-trusted-headers

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string-array</code>                   |
| Environment | <code>$CODER_PROXY_TRUSTED_HEADERS</code>   |
| YAML        | <code>networking.proxyTrustedHeaders</code> |

Headers to trust for forwarding IP addresses. e.g. Cf-Connecting-Ip, True-Client-Ip, X-Forwarded-For.

### --proxy-trusted-origins

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string-array</code>                   |
| Environment | <code>$CODER_PROXY_TRUSTED_ORIGINS</code>   |
| YAML        | <code>networking.proxyTrustedOrigins</code> |

Origin addresses to respect "proxy-trusted-headers" and X-Forwarded-Host for subdomain app routing. e.g. 192.168.1.0/24.

### --cache-dir

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string</code>                 |
| Environment | <code>$CODER_CACHE_DIRECTORY</code> |
| YAML        | <code>cacheDir</code>               |
| Default     | <code>~/.cache/coder</code>         |

The directory to cache temporary files. If unspecified and $CACHE_DIRECTORY is set, it will be used for compatibility with systemd. This directory is NOT safe to be configured as a shared directory across coderd/provisionerd replicas.

### --postgres-url

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string</code>                   |
| Environment | <code>$CODER_PG_CONNECTION_URL</code> |

URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven (https://repo1.maven.org/maven2) and store all data in the config root. Access the built-in database with "coder server postgres-builtin-url". Note that any special characters in the URL must be URL-encoded.

### --postgres-auth

|             |                                  |
|-------------|----------------------------------|
| Type        | <code>password\|awsiamrds</code> |
| Environment | <code>$CODER_PG_AUTH</code>      |
| YAML        | <code>pgAuth</code>              |
| Default     | <code>password</code>            |

Type of auth to use when connecting to postgres. For AWS RDS, using IAM authentication (awsiamrds) is recommended.

### --postgres-conn-max-open

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>int</code>                     |
| Environment | <code>$CODER_PG_CONN_MAX_OPEN</code> |
| YAML        | <code>pgConnMaxOpen</code>           |
| Default     | <code>10</code>                      |

Maximum number of open connections to the database. Defaults to 10.

### --postgres-conn-max-idle

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string</code>                  |
| Environment | <code>$CODER_PG_CONN_MAX_IDLE</code> |
| YAML        | <code>pgConnMaxIdle</code>           |
| Default     | <code>auto</code>                    |

Maximum number of idle connections to the database. Set to "auto" (the default) to use max open / 3. Value must be greater or equal to 0; 0 means explicitly no idle connections.

### --secure-auth-cookie

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>bool</code>                        |
| Environment | <code>$CODER_SECURE_AUTH_COOKIE</code>   |
| YAML        | <code>networking.secureAuthCookie</code> |

Controls if the 'Secure' property is set on browser session cookies.

### --samesite-auth-cookie

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>lax\|none</code>                     |
| Environment | <code>$CODER_SAMESITE_AUTH_COOKIE</code>   |
| YAML        | <code>networking.sameSiteAuthCookie</code> |
| Default     | <code>lax</code>                           |

Controls the 'SameSite' property is set on browser session cookies.

### --host-prefix-cookie

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>bool</code>                        |
| Environment | <code>$CODER_HOST_PREFIX_COOKIE</code>   |
| YAML        | <code>networking.hostPrefixCookie</code> |
| Default     | <code>false</code>                       |

Recommended to be enabled. Enables `__Host-` prefix for cookies to guarantee they are only set by the right domain. This change is disruptive to any workspaces built before release 2.31, requiring a workspace restart.

### --terms-of-service-url

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_TERMS_OF_SERVICE_URL</code> |
| YAML        | <code>termsOfServiceURL</code>           |

A URL to an external Terms of Service that must be accepted by users when logging in.

### --strict-transport-security

|             |                                                     |
|-------------|-----------------------------------------------------|
| Type        | <code>int</code>                                    |
| Environment | <code>$CODER_STRICT_TRANSPORT_SECURITY</code>       |
| YAML        | <code>networking.tls.strictTransportSecurity</code> |
| Default     | <code>0</code>                                      |

Controls if the 'Strict-Transport-Security' header is set on all static file responses. This header should only be set if the server is accessed via HTTPS. This value is the MaxAge in seconds of the header.

### --strict-transport-security-options

|             |                                                            |
|-------------|------------------------------------------------------------|
| Type        | <code>string-array</code>                                  |
| Environment | <code>$CODER_STRICT_TRANSPORT_SECURITY_OPTIONS</code>      |
| YAML        | <code>networking.tls.strictTransportSecurityOptions</code> |

Two optional fields can be set in the Strict-Transport-Security header; 'includeSubDomains' and 'preload'. The 'strict-transport-security' flag must be set to a non-zero value for these options to be used.

### --ssh-keygen-algorithm

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_SSH_KEYGEN_ALGORITHM</code> |
| YAML        | <code>sshKeygenAlgorithm</code>          |
| Default     | <code>ed25519</code>                     |

The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096".

### --browser-only

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>bool</code>                   |
| Environment | <code>$CODER_BROWSER_ONLY</code>    |
| YAML        | <code>networking.browserOnly</code> |

Whether Coder only allows connections to workspaces via the browser.

### --cluster-host

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_CLUSTER_HOST</code>            |
| YAML        | <code>networking.cluster.clusterHost</code> |

Hostname or (more commonly) IP to reach this replica for clustering.

### --scim-auth-header

|             |                                      |
|-------------|--------------------------------------|
| Type        | <code>string</code>                  |
| Environment | <code>$CODER_SCIM_AUTH_HEADER</code> |

Enables SCIM and sets the authentication header for the built-in SCIM server. New users are automatically created with OIDC authentication.

### --scim-use-legacy

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>bool</code>                   |
| Environment | <code>$CODER_SCIM_USE_LEGACY</code> |
| YAML        | <code>scimUseLegacy</code>          |
| Default     | <code>true</code>                   |

Use the legacy SCIM implementation instead of the SCIM 2.0 handler. This is provided for backward compatibility for existing users.

### --external-token-encryption-keys

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>string-array</code>                          |
| Environment | <code>$CODER_EXTERNAL_TOKEN_ENCRYPTION_KEYS</code> |

Encrypt OIDC and Git authentication tokens with AES-256-GCM in the database. The value must be a comma-separated list of base64-encoded keys. Each key, when base64-decoded, must be exactly 32 bytes in length. The first key will be used to encrypt new values. Subsequent keys will be used as a fallback when decrypting. During normal operation it is recommended to only set one key unless you are in the process of rotating keys with the `coder server dbcrypt rotate` command.

### --disable-path-apps

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>bool</code>                     |
| Environment | <code>$CODER_DISABLE_PATH_APPS</code> |
| YAML        | <code>disablePathApps</code>          |

Disable workspace apps that are not served from subdomains. Path-based apps can make requests to the Coder API and pose a security risk when the workspace serves malicious JavaScript. This is recommended for security purposes if a --wildcard-access-url is configured.

### --disable-owner-workspace-access

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>bool</code>                                  |
| Environment | <code>$CODER_DISABLE_OWNER_WORKSPACE_ACCESS</code> |
| YAML        | <code>disableOwnerWorkspaceAccess</code>           |

Remove the permission for the 'owner' role to have workspace execution on all workspaces. This prevents the 'owner' from ssh, apps, and terminal access based on the 'owner' role. They still have their user permissions to access their own workspaces.

### --disable-workspace-sharing

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>bool</code>                             |
| Environment | <code>$CODER_DISABLE_WORKSPACE_SHARING</code> |
| YAML        | <code>disableWorkspaceSharing</code>          |

Disable workspace sharing. Workspace ACL checking is disabled and only owners can have ssh, apps and terminal access to workspaces. Access based on the 'owner' role is also allowed unless disabled via --disable-owner-workspace-access.

### --disable-chat-sharing

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>bool</code>                        |
| Environment | <code>$CODER_DISABLE_CHAT_SHARING</code> |
| YAML        | <code>disableChatSharing</code>          |

Disable chat sharing. Chat ACL checking is disabled and only owners can access their chats.

### --disable-chat-caller-supplied-tools

|             |                                                        |
|-------------|--------------------------------------------------------|
| Type        | <code>bool</code>                                      |
| Environment | <code>$CODER_DISABLE_CHAT_CALLER_SUPPLIED_TOOLS</code> |
| YAML        | <code>disableChatCallerSuppliedTools</code>            |

Disable caller-supplied tools in chats. Chat requests that include unsafe_dynamic_tools or inline_mcp_servers are rejected, and existing chats run without their dynamic tools and inline MCP servers.

### --disable-workspace-agent-context-sync

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>bool</code>                                        |
| Environment | <code>$CODER_DISABLE_WORKSPACE_AGENT_CONTEXT_SYNC</code> |
| YAML        | <code>disableWorkspaceAgentContextSync</code>            |

Stop persisting workspace agent context snapshots (instructions, skills, and MCP state used for pinned chat context). When set, coderd rejects agent context pushes as unimplemented and agents stop sending them; chats cannot pin workspace context. Use this to shed the database write load of context sync on large deployments.

### --disable-user-secret-file-path

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>bool</code>                                 |
| Environment | <code>$CODER_DISABLE_USER_SECRET_FILE_PATH</code> |
| YAML        | <code>disableUserSecretFilePath</code>            |

Disable Coder-managed file path delivery for user secrets. Stored paths remain until users clear them and resume if this setting is turned off.

### --session-duration

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>duration</code>                        |
| Environment | <code>$CODER_SESSION_DURATION</code>         |
| YAML        | <code>networking.http.sessionDuration</code> |
| Default     | <code>24h0m0s</code>                         |

The token expiry duration for browser sessions. Sessions may last longer if they are actively making requests, but this functionality can be disabled via --disable-session-expiry-refresh.

### --disable-session-expiry-refresh

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>bool</code>                                        |
| Environment | <code>$CODER_DISABLE_SESSION_EXPIRY_REFRESH</code>       |
| YAML        | <code>networking.http.disableSessionExpiryRefresh</code> |

Disable automatic session expiry bumping due to activity. This forces all sessions to become invalid after the session expiry duration has been reached.

### --disable-password-auth

|             |                                                  |
|-------------|--------------------------------------------------|
| Type        | <code>bool</code>                                |
| Environment | <code>$CODER_DISABLE_PASSWORD_AUTH</code>        |
| YAML        | <code>networking.http.disablePasswordAuth</code> |

Disable password authentication. This is recommended for security purposes in production deployments that rely on an identity provider. Any user with the owner role will be able to sign in with their password regardless of this setting to avoid potential lock out. If you are locked out of your account, you can use the `coder server create-admin` command to create a new admin user directly in the database.

### -c, --config

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>yaml-config-path</code>   |
| Environment | <code>$CODER_CONFIG_PATH</code> |

Specify a YAML file to load configuration from.

### --workspace-hostname-suffix

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>string</code>                           |
| Environment | <code>$CODER_WORKSPACE_HOSTNAME_SUFFIX</code> |
| YAML        | <code>client.workspaceHostnameSuffix</code>   |
| Default     | <code>coder</code>                            |

Workspace hostnames use this suffix in SSH config and Coder Connect on Coder Desktop. By default it is coder, resulting in names like myworkspace.coder. The suffix must not start with a dot, and must not contain spaces, newlines, or glob characters (* and ?).

### --ssh-config-options

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string-array</code>              |
| Environment | <code>$CODER_SSH_CONFIG_OPTIONS</code> |
| YAML        | <code>client.sshConfigOptions</code>   |

These SSH config options will override the default SSH config options. Provide options in "key=value" or "key value" format separated by commas. Using this incorrectly can break SSH to your deployment, use cautiously. The following options are not allowed: Host, Match, Include, ProxyCommand, ProxyJump, LocalCommand, PermitLocalCommand, RemoteCommand, KnownHostsCommand, PKCS11Provider, SecurityKeyProvider, SmartcardDevice, XAuthLocation. Option values must not contain newline, carriage return, or NUL characters.

### --cli-upgrade-message

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_CLI_UPGRADE_MESSAGE</code> |
| YAML        | <code>client.cliUpgradeMessage</code>   |

The upgrade message to display to users when a client/server mismatch is detected. By default it instructs users to update using 'curl -fsSL https://coder.com/install.sh | sh'.

### --write-config

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

<br/>Write out the current server config as YAML to stdout.

### --support-links

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>struct[[]codersdk.LinkConfig]</code> |
| Environment | <code>$CODER_SUPPORT_LINKS</code>          |
| YAML        | <code>supportLinks</code>                  |

Support links to display in the top right drop down menu.

### --external-auth-github-default-provider-enable

|             |                                                                  |
|-------------|------------------------------------------------------------------|
| Type        | <code>bool</code>                                                |
| Environment | <code>$CODER_EXTERNAL_AUTH_GITHUB_DEFAULT_PROVIDER_ENABLE</code> |
| YAML        | <code>externalAuthGithubDefaultProviderEnable</code>             |
| Default     | <code>true</code>                                                |

Enable the default GitHub external auth provider managed by Coder.

### --proxy-health-interval

|             |                                                  |
|-------------|--------------------------------------------------|
| Type        | <code>duration</code>                            |
| Environment | <code>$CODER_PROXY_HEALTH_INTERVAL</code>        |
| YAML        | <code>networking.http.proxyHealthInterval</code> |
| Default     | <code>1m0s</code>                                |

The interval in which coderd should be checking the status of workspace proxies.

### --default-quiet-hours-schedule

|             |                                                               |
|-------------|---------------------------------------------------------------|
| Type        | <code>string</code>                                           |
| Environment | <code>$CODER_QUIET_HOURS_DEFAULT_SCHEDULE</code>              |
| YAML        | <code>userQuietHoursSchedule.defaultQuietHoursSchedule</code> |
| Default     | <code>CRON_TZ=UTC 0 0 ** *</code>                             |

The default daily cron schedule applied to users that haven't set a custom quiet hours schedule themselves. The quiet hours schedule determines when workspaces will be force stopped due to the template's autostop requirement, and will round the max deadline up to be within the user's quiet hours window (or default). The format is the same as the standard cron format, but the day-of-month, month and day-of-week must be *. Only one hour and minute can be specified (ranges or comma separated values are not supported).

### --allow-custom-quiet-hours

|             |                                                           |
|-------------|-----------------------------------------------------------|
| Type        | <code>bool</code>                                         |
| Environment | <code>$CODER_ALLOW_CUSTOM_QUIET_HOURS</code>              |
| YAML        | <code>userQuietHoursSchedule.allowCustomQuietHours</code> |
| Default     | <code>true</code>                                         |

Allow users to set their own quiet hours schedule for workspaces to stop in (depending on template autostop requirement settings). If false, users can't change their quiet hours schedule and the site default is always used.

### --web-terminal-renderer

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>string</code>                       |
| Environment | <code>$CODER_WEB_TERMINAL_RENDERER</code> |
| YAML        | <code>client.webTerminalRenderer</code>   |
| Default     | <code>canvas</code>                       |

The renderer to use when opening a web terminal. Valid values are 'canvas', 'webgl', or 'dom'.

### --health-check-refresh

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>duration</code>                          |
| Environment | <code>$CODER_HEALTH_CHECK_REFRESH</code>       |
| YAML        | <code>introspection.healthcheck.refresh</code> |
| Default     | <code>10m0s</code>                             |

Refresh interval for healthchecks.

### --health-check-threshold-database

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>duration</code>                                    |
| Environment | <code>$CODER_HEALTH_CHECK_THRESHOLD_DATABASE</code>      |
| YAML        | <code>introspection.healthcheck.thresholdDatabase</code> |
| Default     | <code>15ms</code>                                        |

The threshold for the database health check. If the median latency of the database exceeds this threshold over 5 attempts, the database is considered unhealthy. The default value is 15ms.

### --email-from

|             |                                |
|-------------|--------------------------------|
| Type        | <code>string</code>            |
| Environment | <code>$CODER_EMAIL_FROM</code> |
| YAML        | <code>email.from</code>        |

The sender's address to use.

### --email-smarthost

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>string</code>                 |
| Environment | <code>$CODER_EMAIL_SMARTHOST</code> |
| YAML        | <code>email.smarthost</code>        |

The intermediary SMTP host through which emails are sent.

### --email-hello

|             |                                 |
|-------------|---------------------------------|
| Type        | <code>string</code>             |
| Environment | <code>$CODER_EMAIL_HELLO</code> |
| YAML        | <code>email.hello</code>        |
| Default     | <code>localhost</code>          |

The hostname identifying the SMTP server.

### --email-force-tls

|             |                                     |
|-------------|-------------------------------------|
| Type        | <code>bool</code>                   |
| Environment | <code>$CODER_EMAIL_FORCE_TLS</code> |
| YAML        | <code>email.forceTLS</code>         |
| Default     | <code>false</code>                  |

Force a TLS connection to the configured SMTP smarthost.

### --email-auth-identity

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_EMAIL_AUTH_IDENTITY</code> |
| YAML        | <code>email.emailAuth.identity</code>   |

Identity to use with PLAIN authentication.

### --email-auth-username

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_EMAIL_AUTH_USERNAME</code> |
| YAML        | <code>email.emailAuth.username</code>   |

Username to use with PLAIN/LOGIN authentication.

### --email-auth-password

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_EMAIL_AUTH_PASSWORD</code> |

Password to use with PLAIN/LOGIN authentication.

### --email-auth-password-file

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>string</code>                          |
| Environment | <code>$CODER_EMAIL_AUTH_PASSWORD_FILE</code> |
| YAML        | <code>email.emailAuth.passwordFile</code>    |

File from which to load password for use with PLAIN/LOGIN authentication.

### --email-tls-starttls

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>bool</code>                      |
| Environment | <code>$CODER_EMAIL_TLS_STARTTLS</code> |
| YAML        | <code>email.emailTLS.startTLS</code>   |

Enable STARTTLS to upgrade insecure SMTP connections using TLS.

### --email-tls-server-name

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_EMAIL_TLS_SERVERNAME</code> |
| YAML        | <code>email.emailTLS.serverName</code>   |

Server name to verify against the target certificate.

### --email-tls-skip-verify

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>bool</code>                              |
| Environment | <code>$CODER_EMAIL_TLS_SKIPVERIFY</code>       |
| YAML        | <code>email.emailTLS.insecureSkipVerify</code> |

Skip verification of the target server's certificate (insecure).

### --email-tls-ca-cert-file

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_EMAIL_TLS_CACERTFILE</code> |
| YAML        | <code>email.emailTLS.caCertFile</code>   |

CA certificate file to use.

### --email-tls-cert-file

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>string</code>                    |
| Environment | <code>$CODER_EMAIL_TLS_CERTFILE</code> |
| YAML        | <code>email.emailTLS.certFile</code>   |

Certificate file to use.

### --email-tls-cert-key-file

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>string</code>                       |
| Environment | <code>$CODER_EMAIL_TLS_CERTKEYFILE</code> |
| YAML        | <code>email.emailTLS.certKeyFile</code>   |

Certificate key file to use.

### --notifications-method

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_NOTIFICATIONS_METHOD</code> |
| YAML        | <code>notifications.method</code>        |
| Default     | <code>smtp</code>                        |

Which delivery method to use (available options: 'smtp', 'webhook').

### --notifications-dispatch-timeout

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>duration</code>                              |
| Environment | <code>$CODER_NOTIFICATIONS_DISPATCH_TIMEOUT</code> |
| YAML        | <code>notifications.dispatchTimeout</code>         |
| Default     | <code>1m0s</code>                                  |

How long to wait while a notification is being sent before giving up.

### --notifications-email-from

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>string</code>                          |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_FROM</code> |
| YAML        | <code>notifications.email.from</code>        |

The sender's address to use.

### --notifications-email-smarthost

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>string</code>                               |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_SMARTHOST</code> |
| YAML        | <code>notifications.email.smarthost</code>        |

The intermediary SMTP host through which emails are sent.

### --notifications-email-hello

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>string</code>                           |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_HELLO</code> |
| YAML        | <code>notifications.email.hello</code>        |

The hostname identifying the SMTP server.

### --notifications-email-force-tls

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>bool</code>                                 |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_FORCE_TLS</code> |
| YAML        | <code>notifications.email.forceTLS</code>         |

Force a TLS connection to the configured SMTP smarthost.

### --notifications-email-auth-identity

|             |                                                       |
|-------------|-------------------------------------------------------|
| Type        | <code>string</code>                                   |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_AUTH_IDENTITY</code> |
| YAML        | <code>notifications.email.emailAuth.identity</code>   |

Identity to use with PLAIN authentication.

### --notifications-email-auth-username

|             |                                                       |
|-------------|-------------------------------------------------------|
| Type        | <code>string</code>                                   |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_AUTH_USERNAME</code> |
| YAML        | <code>notifications.email.emailAuth.username</code>   |

Username to use with PLAIN/LOGIN authentication.

### --notifications-email-auth-password

|             |                                                       |
|-------------|-------------------------------------------------------|
| Type        | <code>string</code>                                   |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD</code> |

Password to use with PLAIN/LOGIN authentication.

### --notifications-email-auth-password-file

|             |                                                            |
|-------------|------------------------------------------------------------|
| Type        | <code>string</code>                                        |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_AUTH_PASSWORD_FILE</code> |
| YAML        | <code>notifications.email.emailAuth.passwordFile</code>    |

File from which to load password for use with PLAIN/LOGIN authentication.

### --notifications-email-tls-starttls

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>bool</code>                                    |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_TLS_STARTTLS</code> |
| YAML        | <code>notifications.email.emailTLS.startTLS</code>   |

Enable STARTTLS to upgrade insecure SMTP connections using TLS.

### --notifications-email-tls-server-name

|             |                                                        |
|-------------|--------------------------------------------------------|
| Type        | <code>string</code>                                    |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_TLS_SERVERNAME</code> |
| YAML        | <code>notifications.email.emailTLS.serverName</code>   |

Server name to verify against the target certificate.

### --notifications-email-tls-skip-verify

|             |                                                              |
|-------------|--------------------------------------------------------------|
| Type        | <code>bool</code>                                            |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_TLS_SKIPVERIFY</code>       |
| YAML        | <code>notifications.email.emailTLS.insecureSkipVerify</code> |

Skip verification of the target server's certificate (insecure).

### --notifications-email-tls-ca-cert-file

|             |                                                        |
|-------------|--------------------------------------------------------|
| Type        | <code>string</code>                                    |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_TLS_CACERTFILE</code> |
| YAML        | <code>notifications.email.emailTLS.caCertFile</code>   |

CA certificate file to use.

### --notifications-email-tls-cert-file

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>string</code>                                  |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_TLS_CERTFILE</code> |
| YAML        | <code>notifications.email.emailTLS.certFile</code>   |

Certificate file to use.

### --notifications-email-tls-cert-key-file

|             |                                                         |
|-------------|---------------------------------------------------------|
| Type        | <code>string</code>                                     |
| Environment | <code>$CODER_NOTIFICATIONS_EMAIL_TLS_CERTKEYFILE</code> |
| YAML        | <code>notifications.email.emailTLS.certKeyFile</code>   |

Certificate key file to use.

### --notifications-webhook-endpoint

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>url</code>                                   |
| Environment | <code>$CODER_NOTIFICATIONS_WEBHOOK_ENDPOINT</code> |
| YAML        | <code>notifications.webhook.endpoint</code>        |

The endpoint to which to send webhooks.

### --notifications-inbox-enabled

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>bool</code>                               |
| Environment | <code>$CODER_NOTIFICATIONS_INBOX_ENABLED</code> |
| YAML        | <code>notifications.inbox.enabled</code>        |
| Default     | <code>true</code>                               |

Enable Coder Inbox.

### --notifications-max-send-attempts

|             |                                                     |
|-------------|-----------------------------------------------------|
| Type        | <code>int</code>                                    |
| Environment | <code>$CODER_NOTIFICATIONS_MAX_SEND_ATTEMPTS</code> |
| YAML        | <code>notifications.maxSendAttempts</code>          |
| Default     | <code>5</code>                                      |

The upper limit of attempts to send a notification.

### --workspace-prebuilds-reconciliation-interval

|             |                                                                 |
|-------------|-----------------------------------------------------------------|
| Type        | <code>duration</code>                                           |
| Environment | <code>$CODER_WORKSPACE_PREBUILDS_RECONCILIATION_INTERVAL</code> |
| YAML        | <code>workspace_prebuilds.reconciliation_interval</code>        |
| Default     | <code>1m0s</code>                                               |

How often to reconcile workspace prebuilds state.

### --chat-debug-logging-enabled

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>bool</code>                              |
| Environment | <code>$CODER_CHAT_DEBUG_LOGGING_ENABLED</code> |
| YAML        | <code>chat.debugLoggingEnabled</code>          |
| Default     | <code>false</code>                             |

Force chat debug logging on for every chat, bypassing the runtime admin and user opt-in settings.

### --chat-max-steps-per-turn

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>int</code>                            |
| Environment | <code>$CODER_CHAT_MAX_STEPS_PER_TURN</code> |
| YAML        | <code>chat.maxStepsPerTurn</code>           |
| Default     | <code>1200</code>                           |

Maximum number of steps in a chat turn. Each model response is one step; compaction summaries, advisor calls, and retried attempts do not count. A turn that reaches the limit runs the tools from the last response, then ends without an error. Must be at least 1.

### --chat-max-generation-retries

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>int</code>                                |
| Environment | <code>$CODER_CHAT_MAX_GENERATION_RETRIES</code> |
| YAML        | <code>chat.maxGenerationRetries</code>          |
| Default     | <code>25</code>                                 |

Maximum number of consecutive retries after a model generation fails with a transient error, such as a rate limit, an overloaded provider, or a stream that stops sending data. The count resets after each successful step. When the retries run out, the chat moves to the error state and shows the provider error. Advisor calls and the generation of chat titles, summaries, and turn status labels use the same limit. Must be at least 1.

### --chat-max-queued-messages-per-chat

|             |                                                       |
|-------------|-------------------------------------------------------|
| Type        | <code>int</code>                                      |
| Environment | <code>$CODER_CHAT_MAX_QUEUED_MESSAGES_PER_CHAT</code> |
| YAML        | <code>chat.maxQueuedMessagesPerChat</code>            |
| Default     | <code>20</code>                                       |

Maximum number of messages that can be queued in a chat. Sending a message to a chat whose queue is full fails with HTTP 429. Must be at least 1.

### --chat-max-attachments-per-chat

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>int</code>                                  |
| Environment | <code>$CODER_CHAT_MAX_ATTACHMENTS_PER_CHAT</code> |
| YAML        | <code>chat.maxAttachmentsPerChat</code>           |
| Default     | <code>50</code>                                   |

Maximum number of files linked to a chat, including user uploads, files the agent attaches, and desktop recordings and their thumbnails. Linking a file beyond the limit permanently deletes the chat's earliest-uploaded files, and earlier messages show them as expired. A message that includes more files than the limit is rejected with HTTP 400. Must be at least 1.

### --chat-max-prompt-bytes

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>int</code>                          |
| Environment | <code>$CODER_CHAT_MAX_PROMPT_BYTES</code> |
| YAML        | <code>chat.maxPromptBytes</code>          |
| Default     | <code>131072</code>                       |

Maximum size in bytes of the deployment system prompt, the plan mode instructions, and each user's custom prompt. Saving a longer prompt fails with HTTP 400. Lowering the limit does not affect prompts that are already saved. Must be at least 1.

### --chat-max-concurrent-recording-uploads

|             |                                                           |
|-------------|-----------------------------------------------------------|
| Type        | <code>int</code>                                          |
| Environment | <code>$CODER_CHAT_MAX_CONCURRENT_RECORDING_UPLOADS</code> |
| YAML        | <code>chat.maxConcurrentRecordingUploads</code>           |
| Default     | <code>25</code>                                           |

Maximum number of virtual desktop recordings that each Coder server stores at the same time. Each upload holds the recording and its thumbnail in memory, up to 110 MB. Additional recordings wait for a free slot and are discarded if none frees up within 90 seconds. Must be at least 1.

### --chat-stream-silence-timeout

|             |                                                 |
|-------------|-------------------------------------------------|
| Type        | <code>duration</code>                           |
| Environment | <code>$CODER_CHAT_STREAM_SILENCE_TIMEOUT</code> |
| YAML        | <code>chat.streamSilenceTimeout</code>          |
| Default     | <code>10m0s</code>                              |

Maximum time to wait for the next streamed part from the chat model before the attempt is canceled and retried. This also bounds the time to first token. Set to 0 to disable. Must be no more than 24h.

### --ai-gateway-enabled

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>bool</code>                      |
| Environment | <code>$CODER_AI_GATEWAY_ENABLED</code> |
| YAML        | <code>ai_gateway.enabled</code>        |
| Default     | <code>true</code>                      |

Whether to start an in-memory AI Gateway instance.

### --ai-gateway-retention

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>duration</code>                    |
| Environment | <code>$CODER_AI_GATEWAY_RETENTION</code> |
| YAML        | <code>ai_gateway.retention</code>        |
| Default     | <code>60d</code>                         |

Length of time to retain data such as interceptions and all related records (token, prompt, tool use).

### --ai-gateway-max-concurrency

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>int</code>                               |
| Environment | <code>$CODER_AI_GATEWAY_MAX_CONCURRENCY</code> |
| YAML        | <code>ai_gateway.max_concurrency</code>        |
| Default     | <code>0</code>                                 |

Maximum number of concurrent AI Gateway requests per replica. Set to 0 to disable (unlimited).

### --ai-gateway-rate-limit

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>int</code>                          |
| Environment | <code>$CODER_AI_GATEWAY_RATE_LIMIT</code> |
| YAML        | <code>ai_gateway.rate_limit</code>        |
| Default     | <code>0</code>                            |

Maximum number of AI Gateway requests per second per replica. Set to 0 to disable (unlimited).

### --ai-gateway-structured-logging

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>bool</code>                                 |
| Environment | <code>$CODER_AI_GATEWAY_STRUCTURED_LOGGING</code> |
| YAML        | <code>ai_gateway.structured_logging</code>        |
| Default     | <code>false</code>                                |

Emit structured logs for AI Gateway interception records. Use this for exporting these records to external SIEM or observability systems.

### --ai-gateway-structured-logging-source

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>coderd\|gateway\|both</code>                       |
| Environment | <code>$CODER_AI_GATEWAY_STRUCTURED_LOGGING_SOURCE</code> |
| YAML        | <code>ai_gateway.structured_logging_source</code>        |
| Default     | <code>coderd</code>                                      |

Which process emits AI Gateway interception records when structured logging is enabled: coderd, the gateway, or both. The gateway emits records that are never persisted, such as those dropped by --ai-gateway-disable-content-recording, but cannot report thread_parent_id or thread_root_id. Use both to verify a move from one to the other; records reaching coderd are then reported twice. A standalone gateway must be configured to emit its own records, and its logs shipped rather than coderd's.

### --ai-gateway-disable-content-recording

|             |                                                          |
|-------------|----------------------------------------------------------|
| Type        | <code>bool</code>                                        |
| Environment | <code>$CODER_AI_GATEWAY_DISABLE_CONTENT_RECORDING</code> |
| YAML        | <code>ai_gateway.disable_content_recording</code>        |
| Default     | <code>false</code>                                       |

Stop recording the content of intercepted conversations. No user prompt, tool call or model reasoning record is stored, including tool names and the arguments they were called with. Interceptions and token usage are still recorded, so cost controls, budget enforcement and spend reporting are unaffected. Sessions show no conversation detail, prompt and tool call telemetry report zero, and interceptions are no longer grouped into threads for clients that do not send their own session ID. Combine with --ai-gateway-structured-logging-source=gateway to keep exporting these records to a SIEM instead.

### --ai-gateway-send-actor-headers

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>bool</code>                                 |
| Environment | <code>$CODER_AI_GATEWAY_SEND_ACTOR_HEADERS</code> |
| YAML        | <code>ai_gateway.send_actor_headers</code>        |
| Default     | <code>false</code>                                |

Add configured headers identifying the authenticated user to intercepted upstream requests. Use this when a proxy between AI Gateway and an upstream AI provider needs user identity. When enabled, removes client-supplied headers at configured actor-header destinations before adding authenticated values. Client headers starting with X-AI-Bridge-Actor are always removed.

### --ai-gateway-actor-header-id

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>string</code>                            |
| Environment | <code>$CODER_AI_GATEWAY_ACTOR_HEADER_ID</code> |
| YAML        | <code>ai_gateway.actor_header_id</code>        |
| Default     | <code>X-AI-Bridge-Actor-ID</code>              |

Header name for the authenticated user's ID. Empty disables this header. Requires AI Gateway actor headers to be enabled.

### --ai-gateway-actor-header-username

|             |                                                      |
|-------------|------------------------------------------------------|
| Type        | <code>string</code>                                  |
| Environment | <code>$CODER_AI_GATEWAY_ACTOR_HEADER_USERNAME</code> |
| YAML        | <code>ai_gateway.actor_header_username</code>        |
| Default     | <code>X-AI-Bridge-Actor-Metadata-Username</code>     |

Header name for the authenticated user's username. Empty disables this header. Requires AI Gateway actor headers to be enabled.

### --ai-gateway-actor-header-email

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>string</code>                               |
| Environment | <code>$CODER_AI_GATEWAY_ACTOR_HEADER_EMAIL</code> |
| YAML        | <code>ai_gateway.actor_header_email</code>        |

Header name for the authenticated user's email address. Empty disables this header. Requires AI Gateway actor headers to be enabled. Applies to every configured provider; email is personal information.

### --ai-gateway-dump-dir

|             |                                         |
|-------------|-----------------------------------------|
| Type        | <code>string</code>                     |
| Environment | <code>$CODER_AI_GATEWAY_DUMP_DIR</code> |
| YAML        | <code>ai_gateway.api_dump_dir</code>    |

Base directory for dumping AI Gateway request/response pairs to disk for debugging. When set, each provider writes under a subdirectory named after the provider. Sensitive headers are redacted. Leave empty to disable.

### --ai-gateway-allow-byok

|             |                                           |
|-------------|-------------------------------------------|
| Type        | <code>bool</code>                         |
| Environment | <code>$CODER_AI_GATEWAY_ALLOW_BYOK</code> |
| YAML        | <code>ai_gateway.allow_byok</code>        |
| Default     | <code>true</code>                         |

Allow users to provide their own LLM API keys or subscriptions. When disabled, only centralized key authentication is permitted.

### --ai-gateway-circuit-breaker-enabled

|             |                                                        |
|-------------|--------------------------------------------------------|
| Type        | <code>bool</code>                                      |
| Environment | <code>$CODER_AI_GATEWAY_CIRCUIT_BREAKER_ENABLED</code> |
| YAML        | <code>ai_gateway.circuit_breaker_enabled</code>        |
| Default     | <code>false</code>                                     |

Enable the circuit breaker to protect against cascading failures from upstream AI provider overload (503, 529).

### --ai-budget-policy

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>highest</code>                  |
| Environment | <code>$CODER_AI_BUDGET_POLICY</code>  |
| YAML        | <code>ai_gateway.budget_policy</code> |
| Default     | <code>highest</code>                  |

Determines the effective group when a user belongs to multiple groups with AI budgets. "highest" selects the group with the largest spend limit, and is currently the only supported value.

### --ai-budget-period

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>month</code>                    |
| Environment | <code>$CODER_AI_BUDGET_PERIOD</code>  |
| YAML        | <code>ai_gateway.budget_period</code> |
| Default     | <code>month</code>                    |

Determines when accumulated AI spend resets to zero, aligned to UTC calendar boundaries. Only "month" is currently supported.

### --ai-gateway-proxy-enabled

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>bool</code>                            |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_ENABLED</code> |
| YAML        | <code>ai_gateway_proxy.enabled</code>        |
| Default     | <code>false</code>                           |

Enable the AI Gateway MITM Proxy for intercepting and decrypting AI provider requests.

### --ai-gateway-proxy-listen-addr

|             |                                                  |
|-------------|--------------------------------------------------|
| Type        | <code>string</code>                              |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_LISTEN_ADDR</code> |
| YAML        | <code>ai_gateway_proxy.listen_addr</code>        |
| Default     | <code>:8888</code>                               |

The address the AI Gateway Proxy will listen on.

### --ai-gateway-proxy-target

|             |                                             |
|-------------|---------------------------------------------|
| Type        | <code>string</code>                         |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_TARGET</code> |
| YAML        | <code>ai_gateway_proxy.target</code>        |

Base URL of the AI Gateway to forward intercepted requests to. Defaults to the embedded AI Gateway address at the Coder access URL plus /api/v2/ai-gateway.

### --ai-gateway-proxy-tls-cert-file

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>string</code>                                |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_TLS_CERT_FILE</code> |
| YAML        | <code>ai_gateway_proxy.tls_cert_file</code>        |

Path to the TLS certificate file for the AI Gateway Proxy listener. Must be set together with AI Gateway Proxy TLS Key File.

### --ai-gateway-proxy-tls-key-file

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>string</code>                               |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_TLS_KEY_FILE</code> |
| YAML        | <code>ai_gateway_proxy.tls_key_file</code>        |

Path to the TLS private key file for the AI Gateway Proxy listener. Must be set together with AI Gateway Proxy TLS Certificate File.

### --ai-gateway-proxy-cert-file

|             |                                                |
|-------------|------------------------------------------------|
| Type        | <code>string</code>                            |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_CERT_FILE</code> |
| YAML        | <code>ai_gateway_proxy.cert_file</code>        |

Path to the CA certificate file used to intercept (MITM) HTTPS traffic from AI clients. This CA must be trusted by AI clients for the proxy to decrypt their requests.

### --ai-gateway-proxy-key-file

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>string</code>                           |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_KEY_FILE</code> |
| YAML        | <code>ai_gateway_proxy.key_file</code>        |

Path to the CA private key file used to intercept (MITM) HTTPS traffic from AI clients.

### --ai-gateway-proxy-upstream

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>string</code>                           |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_UPSTREAM</code> |
| YAML        | <code>ai_gateway_proxy.upstream_proxy</code>  |

URL of an upstream HTTP proxy to chain tunneled (non-allowlisted) requests through. Format: http://[user:pass@]host:port or https://[user:pass@]host:port.

### --ai-gateway-proxy-upstream-ca

|             |                                                  |
|-------------|--------------------------------------------------|
| Type        | <code>string</code>                              |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_UPSTREAM_CA</code> |
| YAML        | <code>ai_gateway_proxy.upstream_proxy_ca</code>  |

Path to a PEM-encoded CA certificate to trust for the upstream proxy's TLS connection. Only needed for HTTPS upstream proxies with certificates not trusted by the system. If not provided, the system certificate pool is used.

### --ai-gateway-proxy-allowed-private-cidrs

|             |                                                            |
|-------------|------------------------------------------------------------|
| Type        | <code>string-array</code>                                  |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_ALLOWED_PRIVATE_CIDRS</code> |
| YAML        | <code>ai_gateway_proxy.allowed_private_cidrs</code>        |

Comma-separated list of CIDR ranges that are permitted even though they fall within blocked private/reserved IP ranges. By default all private ranges are blocked to prevent SSRF attacks. Use this to allow access to specific internal networks.

### --ai-gateway-proxy-dump-dir

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>string</code>                           |
| Environment | <code>$CODER_AI_GATEWAY_PROXY_DUMP_DIR</code> |
| YAML        | <code>ai_gateway_proxy.api_dump_dir</code>    |

Directory for dumping MITM request/response pairs to disk for debugging. When set, each proxied request produces .req.txt and .resp.txt files organized by provider. Sensitive headers are redacted. Leave empty to disable.

### --audit-logs-retention

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>duration</code>                    |
| Environment | <code>$CODER_AUDIT_LOGS_RETENTION</code> |
| YAML        | <code>retention.audit_logs</code>        |
| Default     | <code>0</code>                           |

How long audit log entries are retained. Set to 0 to disable (keep indefinitely). We advise keeping audit logs for at least a year, and in accordance with your compliance requirements.

### --connection-logs-retention

|             |                                               |
|-------------|-----------------------------------------------|
| Type        | <code>duration</code>                         |
| Environment | <code>$CODER_CONNECTION_LOGS_RETENTION</code> |
| YAML        | <code>retention.connection_logs</code>        |
| Default     | <code>0</code>                                |

How long connection log entries are retained. Set to 0 to disable (keep indefinitely).

### --api-keys-retention

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>duration</code>                  |
| Environment | <code>$CODER_API_KEYS_RETENTION</code> |
| YAML        | <code>retention.api_keys</code>        |
| Default     | <code>7d</code>                        |

How long expired API keys are retained before being deleted. Keeping expired keys allows the backend to return a more helpful error when a user tries to use an expired key. Set to 0 to disable automatic deletion of expired keys.

### --workspace-agent-logs-retention

|             |                                                    |
|-------------|----------------------------------------------------|
| Type        | <code>duration</code>                              |
| Environment | <code>$CODER_WORKSPACE_AGENT_LOGS_RETENTION</code> |
| YAML        | <code>retention.workspace_agent_logs</code>        |
| Default     | <code>7d</code>                                    |

How long workspace agent logs are retained. Logs from non-latest builds are deleted if the agent hasn't connected within this period. Logs from the latest build are always retained. Set to 0 to disable automatic deletion.

### --boundary-log-retention

|             |                                            |
|-------------|--------------------------------------------|
| Type        | <code>duration</code>                      |
| Environment | <code>$CODER_BOUNDARY_LOG_RETENTION</code> |
| YAML        | <code>retention.boundary_logs</code>       |
| Default     | <code>0</code>                             |

How long boundary audit log entries are retained. Boundary logs record HTTP requests processed by a Boundary confinement proxy. Set to 0 to disable automatic deletion (keep indefinitely). Adjust to match your organization's regulatory requirements.

### --disable-template-builder

|             |                                              |
|-------------|----------------------------------------------|
| Type        | <code>bool</code>                            |
| Environment | <code>$CODER_DISABLE_TEMPLATE_BUILDER</code> |
| YAML        | <code>templateBuilder.disabled</code>        |

Disable the template builder feature for guided template creation. When disabled, all /api/v2/templatebuilder/* endpoints return 404.

### --template-builder-registry-url

|             |                                                   |
|-------------|---------------------------------------------------|
| Type        | <code>string</code>                               |
| Environment | <code>$CODER_TEMPLATE_BUILDER_REGISTRY_URL</code> |
| YAML        | <code>templateBuilder.registryURL</code>          |
| Default     | <code>registry.coder.com</code>                   |

The module registry host the template builder uses for module source paths (for example, "registry.coder.com" or "mirror.internal:8443"). An http(s):// scheme and trailing slash are stripped; a path, query, fragment, or credentials is rejected.

---

# coder server create-admin-user

Source: https://coder.com/docs/reference/cli/server/create-admin-user

<!-- DO NOT EDIT | GENERATED CONTENT -->

Create a new admin user with the given username, email and password and adds it to every organization.

## Usage

```console
coder server create-admin-user [flags]
```

## Options

### --postgres-url

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string</code>                   |
| Environment | <code>$CODER_PG_CONNECTION_URL</code> |

URL of a PostgreSQL database. If empty, the built-in PostgreSQL deployment will be used (Coder must not be already running in this case).

### --postgres-connection-auth

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>password\|awsiamrds</code>       |
| Environment | <code>$CODER_PG_CONNECTION_AUTH</code> |
| Default     | <code>password</code>                  |

Type of auth to use when connecting to postgres.

### --ssh-keygen-algorithm

|             |                                          |
|-------------|------------------------------------------|
| Type        | <code>string</code>                      |
| Environment | <code>$CODER_SSH_KEYGEN_ALGORITHM</code> |
| Default     | <code>ed25519</code>                     |

The algorithm to use for generating ssh keys. Accepted values are "ed25519", "ecdsa", or "rsa4096".

### --username

|             |                              |
|-------------|------------------------------|
| Type        | <code>string</code>          |
| Environment | <code>$CODER_USERNAME</code> |

The username of the new user. If not specified, you will be prompted via stdin.

### --email

|             |                           |
|-------------|---------------------------|
| Type        | <code>string</code>       |
| Environment | <code>$CODER_EMAIL</code> |

The email of the new user. If not specified, you will be prompted via stdin.

### --password

|             |                              |
|-------------|------------------------------|
| Type        | <code>string</code>          |
| Environment | <code>$CODER_PASSWORD</code> |

The password of the new user. If not specified, you will be prompted via stdin.

### --raw-url

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Output the raw connection URL instead of a psql command.

---

# coder server dbcrypt

Source: https://coder.com/docs/reference/cli/server/dbcrypt

<!-- DO NOT EDIT | GENERATED CONTENT -->

Manage database encryption.

## Usage

```console
coder server dbcrypt
```

## Subcommands

| Name                                 | Purpose                                                                       |
|--------------------------------------|-------------------------------------------------------------------------------|
| [<code>decrypt</code>](./decrypt.md) | Decrypt a previously encrypted database.                                      |
| [<code>delete</code>](./delete.md)   | Delete all encrypted data from the database. THIS IS A DESTRUCTIVE OPERATION. |
| [<code>rotate</code>](./rotate.md)   | Rotate database encryption keys.                                              |

---

# coder server dbcrypt decrypt

Source: https://coder.com/docs/reference/cli/server/dbcrypt/decrypt

<!-- DO NOT EDIT | GENERATED CONTENT -->

Decrypt a previously encrypted database.

## Usage

```console
coder server dbcrypt decrypt [flags]
```

## Options

### --postgres-url

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string</code>                   |
| Environment | <code>$CODER_PG_CONNECTION_URL</code> |

The connection URL for the Postgres database.

### --postgres-connection-auth

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>password\|awsiamrds</code>       |
| Environment | <code>$CODER_PG_CONNECTION_AUTH</code> |
| Default     | <code>password</code>                  |

Type of auth to use when connecting to postgres.

### --keys

|             |                                                            |
|-------------|------------------------------------------------------------|
| Type        | <code>string-array</code>                                  |
| Environment | <code>$CODER_EXTERNAL_TOKEN_ENCRYPTION_DECRYPT_KEYS</code> |

Keys required to decrypt existing data. Must be a comma-separated list of base64-encoded keys.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder server dbcrypt delete

Source: https://coder.com/docs/reference/cli/server/dbcrypt/delete

<!-- DO NOT EDIT | GENERATED CONTENT -->

Delete all encrypted data from the database. THIS IS A DESTRUCTIVE OPERATION.

Aliases:

* rm

## Usage

```console
coder server dbcrypt delete [flags]
```

## Options

### --postgres-url

|             |                                                            |
|-------------|------------------------------------------------------------|
| Type        | <code>string</code>                                        |
| Environment | <code>$CODER_EXTERNAL_TOKEN_ENCRYPTION_POSTGRES_URL</code> |

The connection URL for the Postgres database.

### --postgres-connection-auth

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>password\|awsiamrds</code>       |
| Environment | <code>$CODER_PG_CONNECTION_AUTH</code> |
| Default     | <code>password</code>                  |

Type of auth to use when connecting to postgres.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder server dbcrypt rotate

Source: https://coder.com/docs/reference/cli/server/dbcrypt/rotate

<!-- DO NOT EDIT | GENERATED CONTENT -->

Rotate database encryption keys.

## Usage

```console
coder server dbcrypt rotate [flags]
```

## Options

### --postgres-url

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string</code>                   |
| Environment | <code>$CODER_PG_CONNECTION_URL</code> |

The connection URL for the Postgres database.

### --postgres-connection-auth

|             |                                        |
|-------------|----------------------------------------|
| Type        | <code>password\|awsiamrds</code>       |
| Environment | <code>$CODER_PG_CONNECTION_AUTH</code> |
| Default     | <code>password</code>                  |

Type of auth to use when connecting to postgres.

### --new-key

|             |                                                               |
|-------------|---------------------------------------------------------------|
| Type        | <code>string</code>                                           |
| Environment | <code>$CODER_EXTERNAL_TOKEN_ENCRYPTION_ENCRYPT_NEW_KEY</code> |

The new external token encryption key. Must be base64-encoded.

### --old-keys

|             |                                                                |
|-------------|----------------------------------------------------------------|
| Type        | <code>string-array</code>                                      |
| Environment | <code>$CODER_EXTERNAL_TOKEN_ENCRYPTION_ENCRYPT_OLD_KEYS</code> |

The old external token encryption keys. Must be a comma-separated list of base64-encoded keys.

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

---

# coder server fix-oidc-links

Source: https://coder.com/docs/reference/cli/server/fix-oidc-links

<!-- DO NOT EDIT | GENERATED CONTENT -->

Reset OIDC linked IDs that do not match the expected issuer, allowing users to re-authenticate.

## Usage

```console
coder server fix-oidc-links [flags]
```

## Options

### -y, --yes

|      |                   |
|------|-------------------|
| Type | <code>bool</code> |

Bypass confirmation prompts.

### --postgres-url

|             |                                       |
|-------------|---------------------------------------|
| Type        | <code>string</code>                   |
|