Full Code of coder/code-server for AI

main d7599ae36090 cached
232 files
813.5 KB
216.1k tokens
231 symbols
2 requests
Download .txt
Showing preview only (870K chars total). Download the full file or copy to clipboard to get everything.
Repository: coder/code-server
Branch: main
Commit: d7599ae36090
Files: 232
Total size: 813.5 KB

Directory structure:
gitextract_zegt8ql3/

├── .dockerignore
├── .editorconfig
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   ├── config.yml
│   │   ├── doc.md
│   │   └── feature-request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── codecov.yml
│   ├── codeql-config.yml
│   ├── dependabot.yaml
│   ├── semantic.yaml
│   ├── stale.yml
│   └── workflows/
│       ├── build.yaml
│       ├── installer.yaml
│       ├── publish.yaml
│       ├── release.yaml
│       ├── scripts.yaml
│       ├── security.yaml
│       └── trivy-docker.yaml
├── .gitignore
├── .gitmodules
├── .node-version
├── .prettierignore
├── .prettierrc.yaml
├── .tours/
│   ├── contributing.tour
│   └── start-development.tour
├── CHANGELOG.md
├── LICENSE
├── ThirdPartyNotices.txt
├── ci/
│   ├── Caddyfile
│   ├── README.md
│   ├── build/
│   │   ├── build-code-server.sh
│   │   ├── build-lib.sh
│   │   ├── build-packages.sh
│   │   ├── build-release.sh
│   │   ├── build-standalone-release.sh
│   │   ├── build-vscode.sh
│   │   ├── clean.sh
│   │   ├── code-server-nfpm.sh
│   │   ├── code-server-user.service
│   │   ├── code-server.sh
│   │   ├── code-server@.service
│   │   ├── nfpm.yaml
│   │   └── npm-postinstall.sh
│   ├── dev/
│   │   ├── doctoc.sh
│   │   ├── gen_icons.sh
│   │   ├── lint-scripts.sh
│   │   ├── postinstall.sh
│   │   ├── preinstall.js
│   │   ├── test-e2e.sh
│   │   ├── test-integration.sh
│   │   ├── test-native.sh
│   │   ├── test-scripts.sh
│   │   ├── test-unit.sh
│   │   └── watch.ts
│   ├── helm-chart/
│   │   ├── .helmignore
│   │   ├── Chart.yaml
│   │   ├── templates/
│   │   │   ├── NOTES.txt
│   │   │   ├── _helpers.tpl
│   │   │   ├── deployment.yaml
│   │   │   ├── ingress.yaml
│   │   │   ├── pvc.yaml
│   │   │   ├── secrets.yaml
│   │   │   ├── service.yaml
│   │   │   ├── serviceaccount.yaml
│   │   │   └── tests/
│   │   │       └── test-connection.yaml
│   │   └── values.yaml
│   ├── lib.sh
│   ├── release-image/
│   │   ├── Dockerfile
│   │   ├── Dockerfile.fedora
│   │   ├── Dockerfile.opensuse
│   │   ├── docker-bake.hcl
│   │   ├── entrypoint-catatonit.sh
│   │   └── entrypoint.sh
│   └── steps/
│       ├── brew-bump.sh
│       ├── docker-buildx-push.sh
│       ├── publish-npm.sh
│       └── steps-lib.sh
├── docs/
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── FAQ.md
│   ├── MAINTAINING.md
│   ├── README.md
│   ├── SECURITY.md
│   ├── android.md
│   ├── coder.md
│   ├── collaboration.md
│   ├── guide.md
│   ├── helm.md
│   ├── install.md
│   ├── ios.md
│   ├── ipad.md
│   ├── manifest.json
│   ├── npm.md
│   ├── requirements.md
│   ├── termux.md
│   ├── triage.md
│   └── upgrade.md
├── eslint.config.mjs
├── flake.nix
├── install.sh
├── package.json
├── patches/
│   ├── base-path.diff
│   ├── cli-window-open.diff
│   ├── clipboard.diff
│   ├── disable-builtin-ext-update.diff
│   ├── display-language.diff
│   ├── external-file-actions.diff
│   ├── fix-build.diff
│   ├── getting-started.diff
│   ├── insecure-notification.diff
│   ├── integration.diff
│   ├── keepalive.diff
│   ├── local-storage.diff
│   ├── logout.diff
│   ├── marketplace.diff
│   ├── proposed-api.diff
│   ├── proxy-uri.diff
│   ├── series
│   ├── service-worker.diff
│   ├── signature-verification.diff
│   ├── sourcemaps.diff
│   ├── store-socket.diff
│   ├── telemetry.diff
│   ├── trusted-domains.diff
│   ├── unique-db.diff
│   ├── update-check.diff
│   └── webview.diff
├── renovate.json
├── src/
│   ├── browser/
│   │   ├── pages/
│   │   │   ├── error.css
│   │   │   ├── error.html
│   │   │   ├── global.css
│   │   │   ├── login.css
│   │   │   └── login.html
│   │   ├── robots.txt
│   │   ├── security.txt
│   │   └── serviceWorker.ts
│   ├── common/
│   │   ├── emitter.ts
│   │   ├── http.ts
│   │   └── util.ts
│   └── node/
│       ├── app.ts
│       ├── cli.ts
│       ├── constants.ts
│       ├── entry.ts
│       ├── heart.ts
│       ├── http.ts
│       ├── i18n/
│       │   ├── index.ts
│       │   └── locales/
│       │       ├── en.json
│       │       ├── ja.json
│       │       ├── th.json
│       │       ├── ur.json
│       │       └── zh-cn.json
│       ├── main.ts
│       ├── proxy.ts
│       ├── routes/
│       │   ├── domainProxy.ts
│       │   ├── errors.ts
│       │   ├── health.ts
│       │   ├── index.ts
│       │   ├── login.ts
│       │   ├── logout.ts
│       │   ├── pathProxy.ts
│       │   ├── update.ts
│       │   └── vscode.ts
│       ├── settings.ts
│       ├── socket.ts
│       ├── update.ts
│       ├── util.ts
│       ├── vscodeSocket.ts
│       ├── wrapper.ts
│       └── wsRouter.ts
├── test/
│   ├── e2e/
│   │   ├── baseFixture.ts
│   │   ├── codeServer.test.ts
│   │   ├── downloads.test.ts
│   │   ├── extensions/
│   │   │   └── test-extension/
│   │   │       ├── .gitignore
│   │   │       ├── extension.ts
│   │   │       ├── package.json
│   │   │       └── tsconfig.json
│   │   ├── extensions.test.ts
│   │   ├── github.test.ts
│   │   ├── login.test.ts
│   │   ├── logout.test.ts
│   │   ├── models/
│   │   │   └── CodeServer.ts
│   │   ├── openHelpAbout.test.ts
│   │   ├── routes.test.ts
│   │   ├── terminal.test.ts
│   │   ├── uploads.test.ts
│   │   └── webview.test.ts
│   ├── integration/
│   │   ├── help.test.ts
│   │   └── installExtension.test.ts
│   ├── package.json
│   ├── playwright.config.ts
│   ├── scripts/
│   │   ├── build-lib.bats
│   │   ├── install.bats
│   │   └── steps-lib.bats
│   ├── tsconfig.json
│   ├── unit/
│   │   ├── common/
│   │   │   ├── emitter.test.ts
│   │   │   ├── http.test.ts
│   │   │   └── util.test.ts
│   │   ├── helpers.test.ts
│   │   └── node/
│   │       ├── app.test.ts
│   │       ├── cli.test.ts
│   │       ├── constants.test.ts
│   │       ├── heart.test.ts
│   │       ├── http.test.ts
│   │       ├── i18n.test.ts
│   │       ├── main.test.ts
│   │       ├── proxy.test.ts
│   │       ├── routes/
│   │       │   ├── errors.test.ts
│   │       │   ├── health.test.ts
│   │       │   ├── login.test.ts
│   │       │   ├── static.test.ts
│   │       │   └── vscode.test.ts
│   │       ├── settings.test.ts
│   │       ├── socket.test.ts
│   │       ├── update.test.ts
│   │       ├── util.test.ts
│   │       ├── vscodeSocket.test.ts
│   │       └── wrapper.test.ts
│   └── utils/
│       ├── constants.ts
│       ├── cssStub.ts
│       ├── globalE2eSetup.ts
│       ├── globalUnitSetup.ts
│       ├── helpers.ts
│       ├── httpserver.ts
│       ├── integration.ts
│       ├── runCodeServerCommand.ts
│       └── wtfnode.ts
├── tsconfig.json
└── typings/
    └── httpolyglot/
        └── index.d.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
**
!release-packages
!ci


================================================
FILE: .editorconfig
================================================
root = true

[*]
indent_style = space
trim_trailing_whitespace = true
indent_size = 2


================================================
FILE: .git-blame-ignore-revs
================================================
# Prettier 3.4.2
9b0340a09276f93c054d705d1b9a5f24cc5dbc97

================================================
FILE: .gitattributes
================================================
*.afdesign filter=lfs diff=lfs merge=lfs -text


================================================
FILE: .github/CODEOWNERS
================================================
* @coder/code-server

ci/helm-chart/ @Matthew-Beckett @alexgorbatchev

docs/install.md @GNUxeava

src/node/i18n/locales/zh-cn.json @zhaozhiming


================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.yml
================================================
name: Bug report
description: File a bug report
labels: ["bug", "triage"]
body:
  - type: checkboxes
    attributes:
      label: Is there an existing issue for this?
      description: Please search to see if an issue already exists for the bug you encountered.
      options:
        - label: I have searched the existing issues
          required: true

  - type: textarea
    attributes:
      label: OS/Web Information
      description: |
        examples:
          - **Web Browser**: Chrome
          - **Local OS**: macOS
          - **Remote OS**: Ubuntu
          - **Remote Architecture**: amd64
          - **`code-server --version`**: 4.0.1

        Please do not just put "latest" for the version.
      value: |
        - Web Browser:
        - Local OS:
        - Remote OS:
        - Remote Architecture:
        - `code-server --version`:
    validations:
      required: true

  - type: textarea
    attributes:
      label: Steps to Reproduce
      description: |
        Please describe exactly how to reproduce the bug. For example:
        1. Open code-server in Firefox
        2. Install extension `foo.bar` from the extensions sidebar
        3. Run command `foo.bar.baz`
      value: |
        1.
        2.
        3.
    validations:
      required: true

  - type: textarea
    attributes:
      label: Expected
      description: What should happen?
    validations:
      required: true

  - type: textarea
    attributes:
      label: Actual
      description: What actually happens?
    validations:
      required: true

  - type: textarea
    id: logs
    attributes:
      label: Logs
      description: Run code-server with the --verbose flag and then paste any relevant logs from the server, from the browser console and/or the browser network tab. For issues with installation, include installation logs (i.e. output of `npm install -g code-server`).
      render: shell

  - type: textarea
    attributes:
      label: Screenshot/Video
      description: Please include a screenshot, gif or screen recording of your issue.
    validations:
      required: false

  - type: dropdown
    attributes:
      label: Does this bug reproduce in native VS Code?
      description: If the bug reproduces in native VS Code, submit the issue upstream instead (https://github.com/microsoft/vscode).
      options:
        - Yes, this is also broken in native VS Code
        - No, this works as expected in native VS Code
        - This cannot be tested in native VS Code
        - I did not test native VS Code
    validations:
      required: true

  - type: dropdown
    attributes:
      label: Does this bug reproduce in VS Code web?
      description: If the bug reproduces in VS Code web, submit the issue upstream instead (https://github.com/microsoft/vscode). You can run VS Code web with `code serve-web` (this is not the same as vscode.dev).
      options:
        - Yes, this is also broken in VS Code web
        - No, this works as expected in VS Code web
        - This cannot be tested in VS Code web
        - I did not test VS Code web
    validations:
      required: true

  - type: dropdown
    attributes:
      label: Does this bug reproduce in GitHub Codespaces?
      description: If the bug reproduces in GitHub Codespaces, submit the issue upstream instead (https://github.com/microsoft/vscode).
      options:
        - Yes, this is also broken in GitHub Codespaces
        - No, this works as expected in GitHub Codespaces
        - This cannot be tested in GitHub Codespaces
        - I did not test GitHub Codespaces
    validations:
      required: true

  - type: checkboxes
    attributes:
      label: Are you accessing code-server over a secure context?
      description: code-server relies on service workers (which only work in secure contexts) for many features. Double-check that you are using a secure context like HTTPS or localhost.
      options:
        - label: I am using a secure context.
          required: false

  - type: textarea
    attributes:
      label: Notes
      description: Please include any addition notes that will help us resolve this issue.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
  - name: Question?
    url: https://github.com/coder/code-server/discussions/new?category_id=22503114
    about: Ask the community for help on our GitHub Discussions board
  - name: code-server Slack Community
    about: Need immediate help or just want to talk? Hop in our Slack. Note - this Slack is not actively monitored by code-server maintainers.
    url: https://cdr.co/join-community


================================================
FILE: .github/ISSUE_TEMPLATE/doc.md
================================================
---
name: Documentation improvement
about: Suggest a documentation improvement
labels: "docs"
---

## What is your suggestion?

## How will this improve the docs?

## Are you interested in submitting a PR for this?


================================================
FILE: .github/ISSUE_TEMPLATE/feature-request.md
================================================
---
name: Feature request
about: Suggest an idea to improve code-server
labels: enhancement
---

## What is your suggestion?

## Why do you want this feature?

## Are there any workarounds to get this functionality today?

## Are you interested in submitting a PR for this?


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
<!--
Please link to the issue this PR solves.
If there is no existing issue, please first create one unless the fix is minor.

Please make sure the base of your PR is the default branch!
-->

Fixes #


================================================
FILE: .github/codecov.yml
================================================
codecov:
  require_ci_to_pass: yes
  allow_coverage_offsets: True

coverage:
  precision: 2
  round: down
  range: "40...70"
  status:
    patch: off
  notify:
    slack:
      default:
        url: secret:v1::tXC7VwEIKYjNU8HRgRv2GdKOSCt5UzpykKZb+o1eCDqBgb2PEqwE3A26QUPYMLo4BO2qtrJhFIvwhUvlPwyzDCNGoNiuZfXr0UeZZ0y1TcZu672R/NBNMwEPO/e1Ye0pHxjzKHnuH7HqbjFucox/RBQLtiL3J56SWGE3JtbkC6o=
        threshold: 1%
        only_pulls: false
        branches:
          - "main"

parsers:
  gcov:
    branch_detection:
      conditional: yes
      loop: yes
      method: no
      macro: no

comment:
  layout: "reach,diff,flags,files,footer"
  behavior: default
  require_changes: no


================================================
FILE: .github/codeql-config.yml
================================================
name: "code-server CodeQL config"


================================================
FILE: .github/dependabot.yaml
================================================
version: 2
updates:
  - package-ecosystem: "github-actions"
    directory: "/"
    schedule:
      interval: "monthly"
      time: "06:00"
      timezone: "America/Chicago"
    labels: []
    commit-message:
      prefix: "chore"

  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "monthly"
      time: "06:00"
      timezone: "America/Chicago"
    commit-message:
      prefix: "chore"
    labels: []
    ignore:
      # Ignore patch updates for all dependencies
      - dependency-name: "*"
        update-types:
          - version-update:semver-patch
      # Ignore major updates to Node.js types, because they need to
      # correspond to the Node.js engine version
      - dependency-name: "@types/node"
        update-types:
          - version-update:semver-major


================================================
FILE: .github/semantic.yaml
================================================
###############################################################################
# This file configures "Semantic Pull Requests", which is documented here:
# https://github.com/zeke/semantic-pull-requests
###############################################################################

# Scopes are optionally supplied after a 'type'. For example, in
#
# feat(docs): autostart ui
#
# '(docs)' is the scope. Scopes are used to signify where the change occurred.
scopes:
  # docs: changes to the code-server documentation.
  - docs

  # vendor: changes to vendored dependencies.
  - vendor

  # deps: changes to code-server's dependencies.
  - deps

  # cs: changes to code specific to code-server.
  - cs

  # cli: changes to the command-line interface.
  - cli

# We only check that the PR title is semantic. The PR title is automatically
# applied to the "Squash & Merge" flow as the suggested commit message, so this
# should suffice unless someone drastically alters the message in that flow.
titleOnly: true

# Types are the 'tag' types in a commit or PR title. For example, in
#
# chore: fix thing
#
# 'chore' is the type.
types:
  # A build of any kind.
  - build

  # A user-facing change that corrects a defect in code-server.
  - fix

  # Any code task that is ignored for changelog purposes. Examples include
  # devbin scripts and internal-only configurations.
  - chore

  # Any work performed on CI.
  - ci

  # Work that directly implements or supports the implementation of a feature.
  - feat

  # A refactor changes code structure without any behavioral change.
  - refactor

  # A git revert for any style of commit.
  - revert

  # Adding tests of any kind. Should be separate from feature or fix
  # implementations. For example, if a commit adds a fix + test, it's a fix
  # commit. If a commit is simply bumping coverage, it's a test commit.
  - test

  # A new release.
  - release


================================================
FILE: .github/stale.yml
================================================
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 180
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 5
# Label to apply when stale.
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
  This issue has been automatically marked as stale because it has not had
  recent activity. It will be closed if no activity occurs in the next 5 days.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false


================================================
FILE: .github/workflows/build.yaml
================================================
name: Build

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

# Cancel in-progress runs for pull requests when developers push
# additional changes, and serialize builds in branches.
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

# Note: if: success() is used in several jobs -
# this ensures that it only executes if all previous jobs succeeded.

# if: steps.cache-node-modules.outputs.cache-hit != 'true'
# will skip running `npm install` if it successfully fetched from cache

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      ci: ${{ steps.filter.outputs.ci }}
      code: ${{ steps.filter.outputs.code }}
      deps: ${{ steps.filter.outputs.deps }}
      docs: ${{ steps.filter.outputs.docs }}
      helm: ${{ steps.filter.outputs.helm }}
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
      - name: Check changed files
        uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            ci:
              - ".github/**"
              - "ci/**"
            docs:
              - "docs/**"
              - "README.md"
              - "CHANGELOG.md"
            helm:
              - "ci/helm-chart/**"
            code:
              - "src/**"
              - "test/**"
            deps:
              - "lib/**"
              - "patches/**"
              - "package-lock.json"
              - "test/package-lock.json"
      - id: debug
        run: |
          echo "${{ toJSON(steps.filter )}}"

  prettier:
    name: Run prettier check
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json
      - run: SKIP_SUBMODULE_DEPS=1 npm ci
      - run: npx prettier --check .

  doctoc:
    name: Doctoc markdown files
    runs-on: ubuntu-22.04
    needs: changes
    if: needs.changes.outputs.docs == 'true'
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json
      - run: SKIP_SUBMODULE_DEPS=1 npm ci
      - run: npm run doctoc

  lint-helm:
    name: Lint Helm chart
    runs-on: ubuntu-22.04
    needs: changes
    if: needs.changes.outputs.helm == 'true'
    steps:
      - uses: actions/checkout@v6
      - uses: azure/setup-helm@v4
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
      - run: helm plugin install https://github.com/instrumenta/helm-kubeval
      - run: helm kubeval ci/helm-chart

  lint-ts:
    name: Lint TypeScript files
    runs-on: ubuntu-22.04
    needs: changes
    if: needs.changes.outputs.code == 'true'
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json
      - run: SKIP_SUBMODULE_DEPS=1 npm ci
      - run: npm run lint:ts

  lint-actions:
    name: Lint GitHub Actions
    runs-on: ubuntu-latest
    needs: changes
    if: needs.changes.outputs.ci == 'true'
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
      - name: Check workflow files
        run: |
          bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash) 1.7.9
          ./actionlint -color -shellcheck= -ignore "softprops/action-gh-release"
        shell: bash

  test-unit:
    name: Run unit tests
    runs-on: ubuntu-22.04
    needs: changes
    if: needs.changes.outputs.code == 'true'
    steps:
      - uses: actions/checkout@v6
      - uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json
      - run: SKIP_SUBMODULE_DEPS=1 npm ci
      - run: npm run test:unit
      - uses: codecov/codecov-action@v5
        if: success()
        with:
          token: ${{ secrets.CODECOV_TOKEN }}

  build:
    name: Build code-server
    runs-on: ubuntu-22.04
    env:
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
      DISABLE_V8_COMPILE_CACHE: 1
    steps:
      - uses: actions/checkout@v6
        with:
          submodules: true
      - run: sudo apt update && sudo apt install -y libkrb5-dev
      - uses: awalsh128/cache-apt-pkgs-action@latest
        with:
          packages: quilt
          version: 1.0
      - run: quilt push -a
      - uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json
      - run: SKIP_SUBMODULE_DEPS=1 npm ci
      - run: npm run build
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      # Get Code's git hash.  When this changes it means the content is
      # different and we need to rebuild.
      - name: Get latest lib/vscode rev
        id: vscode-rev
        run: echo "rev=$(git rev-parse HEAD:./lib/vscode)" >> $GITHUB_OUTPUT
      # We need to rebuild when we have a new version of Code, when any of
      # the patches changed, or when the code-server version changes (since
      # it gets embedded into the code).  Use VSCODE_CACHE_VERSION to
      # force a rebuild.
      - name: Fetch prebuilt Code package from cache
        id: cache-vscode
        uses: actions/cache@v4
        with:
          path: lib/vscode-reh-web-*
          key: vscode-reh-package-${{ secrets.VSCODE_CACHE_VERSION }}-${{ steps.vscode-rev.outputs.rev }}-${{ hashFiles('patches/*.diff', 'ci/build/build-vscode.sh') }}
      - name: Build vscode
        env:
          VERSION: "0.0.0"
        if: steps.cache-vscode.outputs.cache-hit != 'true'
        run: |
          pushd lib/vscode
          npm ci
          popd
          npm run build:vscode
      # The release package does not contain any native modules
      # and is neutral to architecture/os/libc version.
      - run: npm run release
        if: success()
      # https://github.com/actions/upload-artifact/issues/38
      - run: tar -czf package.tar.gz release
      - uses: actions/upload-artifact@v7
        with:
          name: npm-package
          path: ./package.tar.gz

  test-e2e:
    name: Run e2e tests
    runs-on: ubuntu-22.04
    needs: [changes, build]
    if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
    steps:
      - uses: actions/checkout@v6
      - run: sudo apt update && sudo apt install -y libkrb5-dev
      - uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json
      - run: SKIP_SUBMODULE_DEPS=1 npm ci
      - uses: actions/download-artifact@v8
        with:
          name: npm-package
      - run: tar -xzf package.tar.gz
      - run: cd release && npm install --unsafe-perm --omit=dev
      - name: Install Playwright OS dependencies
        run: |
          ./test/node_modules/.bin/playwright install-deps
          ./test/node_modules/.bin/playwright install
      - run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e
      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: failed-test-videos
          path: ./test/test-results
      - run: rm -rf ./release ./test/test-results

  test-e2e-proxy:
    name: Run e2e tests behind proxy
    runs-on: ubuntu-22.04
    needs: [changes, build]
    if: needs.changes.outputs.code == 'true' || needs.changes.outputs.deps == 'true'
    steps:
      - uses: actions/checkout@v6
      - run: sudo apt update && sudo apt install -y libkrb5-dev
      - uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json
      - run: SKIP_SUBMODULE_DEPS=1 npm ci
      - uses: actions/download-artifact@v8
        with:
          name: npm-package
      - run: tar -xzf package.tar.gz
      - run: cd release && npm install --unsafe-perm --omit=dev
      - name: Install Playwright OS dependencies
        run: |
          ./test/node_modules/.bin/playwright install-deps
          ./test/node_modules/.bin/playwright install
      - name: Cache Caddy
        uses: actions/cache@v4
        id: caddy-cache
        with:
          path: |
            ~/.cache/caddy
          key: cache-caddy-2.5.2
      - name: Install Caddy
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        if: steps.caddy-cache.outputs.cache-hit != 'true'
        run: |
          gh release download v2.5.2 --repo caddyserver/caddy --pattern "caddy_2.5.2_linux_amd64.tar.gz"
          mkdir -p ~/.cache/caddy
          tar -xzf caddy_2.5.2_linux_amd64.tar.gz --directory ~/.cache/caddy
      - run: ~/.cache/caddy/caddy start --config ./ci/Caddyfile
      - run: CODE_SERVER_TEST_ENTRY=./release npm run test:e2e:proxy
      - run: ~/.cache/caddy/caddy stop --config ./ci/Caddyfile
        if: always()

      - uses: actions/upload-artifact@v7
        if: always()
        with:
          name: failed-test-videos-proxy
          path: ./test/test-results


================================================
FILE: .github/workflows/installer.yaml
================================================
name: Installer integration

on:
  push:
    branches:
      - main
    paths:
      - "install.sh"
      - ".github/workflows/installer.yaml"
  pull_request:
    branches:
      - main
    paths:
      - "install.sh"
      - ".github/workflows/installer.yaml"

# Cancel in-progress runs for pull requests when developers push
# additional changes, and serialize builds in branches.
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
  contents: read

jobs:
  ubuntu:
    name: Test installer on Ubuntu
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6

      - name: Install code-server
        run: ./install.sh

      - name: Test code-server was installed globally
        run: code-server --help

  alpine:
    name: Test installer on Alpine
    runs-on: ubuntu-latest
    container: "alpine:3.17"
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6

      - name: Install curl
        run: apk add curl

      - name: Add user
        run: adduser coder --disabled-password

      # Standalone should work without root.
      - name: Test standalone to a non-existent prefix
        run: su coder -c "./install.sh --method standalone --prefix /tmp/does/not/yet/exist"

      # We do not actually have Alpine standalone builds so running code-server
      # will not work.
      - name: Test code-server was installed to prefix
        run: test -f /tmp/does/not/yet/exist/bin/code-server

  macos:
    name: Test installer on macOS
    runs-on: macos-latest

    steps:
      - name: Checkout repo
        uses: actions/checkout@v6

      - name: Install code-server
        run: ./install.sh

      - name: Test code-server was installed globally
        run: code-server --help


================================================
FILE: .github/workflows/publish.yaml
================================================
name: Publish code-server

on:
  # Shows the manual trigger in GitHub UI
  # helpful as a back-up in case the GitHub Actions Workflow fails
  workflow_dispatch:
    inputs:
      version:
        description: The version to publish (include "v", i.e. "v4.9.1").
        type: string
        required: true

  release:
    types: [released]

# Cancel in-progress runs for pull requests when developers push
# additional changes, and serialize builds in branches.
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  npm:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code-server
        uses: actions/checkout@v6

      - name: Install Node.js
        uses: actions/setup-node@v6
        with:
          node-version-file: .node-version

      - name: Download npm package from release artifacts
        uses: robinraju/release-downloader@v1.12
        with:
          repository: "coder/code-server"
          tag: ${{ github.event.inputs.version || github.ref_name }}
          fileName: "package.tar.gz"
          out-file-path: "release-npm-package"

      # Strip out the v (v4.9.1 -> 4.9.1).
      - name: Get and set VERSION
        run: |
          TAG="${{ github.event.inputs.version || github.ref_name }}"
          echo "VERSION=${TAG#v}" >> $GITHUB_ENV

      - run: npm run publish:npm
        env:
          VERSION: ${{ env.VERSION }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
          NPM_ENVIRONMENT: "production"

  aur:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    env:
      GH_TOKEN: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}

    steps:
      # We need to checkout code-server so we can get the version
      - name: Checkout code-server
        uses: actions/checkout@v6
        with:
          fetch-depth: 0
          path: "./code-server"

      - name: Checkout code-server-aur repo
        uses: actions/checkout@v6
        with:
          repository: "cdrci/code-server-aur"
          token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }}
          ref: "master"

      - name: Merge in master
        run: |
          git remote add upstream https://github.com/coder/code-server-aur.git
          git fetch upstream
          git merge upstream/master

      - name: Configure git
        run: |
          git config --global user.name cdrci
          git config --global user.email opensource@coder.com

      # Strip out the v (v4.9.1 -> 4.9.1).
      - name: Get and set VERSION
        run: |
          TAG="${{ github.event.inputs.version || github.ref_name }}"
          echo "VERSION=${TAG#v}" >> $GITHUB_ENV

      - name: Validate package
        uses: heyhusen/archlinux-package-action@v3.0.0
        env:
          VERSION: ${{ env.VERSION }}
        with:
          pkgver: ${{ env.VERSION }}
          updpkgsums: true
          srcinfo: true

      - name: Open PR
        # We need to git push -u otherwise gh will prompt
        # asking where to push the branch.
        env:
          VERSION: ${{ env.VERSION }}
        run: |
          git checkout -b update-version-${{ env.VERSION }}
          git add .
          git commit -m "chore: updating version to ${{ env.VERSION }}"
          git push -u origin $(git branch --show)
          gh pr create --repo coder/code-server-aur --title "chore: bump version to ${{ env.VERSION }}" --body "PR opened by @$GITHUB_ACTOR" --assignee $GITHUB_ACTOR

  docker:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code-server
        uses: actions/checkout@v6

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Login to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # Strip out the v (v4.9.1 -> 4.9.1).
      - name: Get and set VERSION
        run: |
          TAG="${{ github.event.inputs.version || github.ref_name }}"
          echo "VERSION=${TAG#v}" >> $GITHUB_ENV

      - name: Download deb artifacts
        uses: robinraju/release-downloader@v1.12
        with:
          repository: "coder/code-server"
          tag: v${{ env.VERSION }}
          fileName: "*.deb"
          out-file-path: "release-packages"

      - name: Download rpm artifacts
        uses: robinraju/release-downloader@v1.12
        with:
          repository: "coder/code-server"
          tag: v${{ env.VERSION }}
          fileName: "*.rpm"
          out-file-path: "release-packages"

      - name: Publish to Docker
        run: ./ci/steps/docker-buildx-push.sh
        env:
          VERSION: ${{ env.VERSION }}
          GITHUB_TOKEN: ${{ github.token }}


================================================
FILE: .github/workflows/release.yaml
================================================
name: Draft release

on:
  workflow_dispatch:
    inputs:
      version:
        description: The version to publish (include "v", i.e. "v4.9.1").
        type: string
        required: true

permissions:
  contents: write # For creating releases.
  discussions: write #  For creating a discussion.

# Cancel in-progress runs for pull requests when developers push
# additional changes
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  package-linux-cross:
    name: ${{ matrix.prefix }}
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: npm-version
    container: "python:3.8-slim-buster"
    strategy:
      matrix:
        include:
          - prefix: x86_64-linux-gnu
            npm_arch: x64
            apt_arch: amd64
            package_arch: amd64
          - prefix: aarch64-linux-gnu
            npm_arch: arm64
            apt_arch: arm64
            package_arch: arm64
          - prefix: arm-linux-gnueabihf
            npm_arch: armv7l
            apt_arch: armhf
            package_arch: armv7l

    env:
      AR: ${{ format('{0}-ar', matrix.prefix) }}
      AS: ${{ format('{0}-as', matrix.prefix) }}
      CC: ${{ format('{0}-gcc', matrix.prefix) }}
      CPP: ${{ format('{0}-cpp', matrix.prefix) }}
      CXX: ${{ format('{0}-g++', matrix.prefix) }}
      FC: ${{ format('{0}-gfortran', matrix.prefix) }}
      LD: ${{ format('{0}-ld', matrix.prefix) }}
      STRIP: ${{ format('{0}-strip', matrix.prefix) }}
      PKG_CONFIG_PATH: ${{ format('/usr/lib/{0}/pkgconfig', matrix.prefix) }}
      TARGET_ARCH: ${{ matrix.apt_arch }}
      npm_config_arch: ${{ matrix.npm_arch }}
      PKG_ARCH: ${{ matrix.package_arch }}
      # Not building from source results in an x86_64 argon2, as if
      # npm_config_arch is being ignored.
      npm_config_build_from_source: true

    steps:
      - name: Checkout repo
        uses: actions/checkout@v6

      - name: Install Node.js
        uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json

      - name: Install cross-compiler and system dependencies
        run: |
          sed -i 's/deb\.debian\.org/archive.debian.org/g' /etc/apt/sources.list
          dpkg --add-architecture $TARGET_ARCH
          apt update && apt install -y --no-install-recommends \
            crossbuild-essential-$TARGET_ARCH \
            libx11-dev:$TARGET_ARCH \
            libx11-xcb-dev:$TARGET_ARCH \
            libxkbfile-dev:$TARGET_ARCH \
            libsecret-1-dev:$TARGET_ARCH \
            libkrb5-dev:$TARGET_ARCH \
            ca-certificates \
            curl wget rsync gettext-base

      - run: SKIP_SUBMODULE_DEPS=1 npm ci

      - name: Install nfpm
        run: |
          mkdir -p ~/.local/bin
          curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
          echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Download npm package
        uses: actions/download-artifact@v8
        with:
          name: npm-release-package

      - run: tar -xzf package.tar.gz
      - run: npm run release:standalone

      - name: Replace node with cross-compile equivalent
        run: |
          node_version=$(node --version)
          wget https://nodejs.org/dist/${node_version}/node-${node_version}-linux-${npm_config_arch}.tar.xz
          tar -xf node-${node_version}-linux-${npm_config_arch}.tar.xz node-${node_version}-linux-${npm_config_arch}/bin/node --strip-components=2
          mv ./node ./release-standalone/lib/node

      # Strip out the v (v4.9.1 -> 4.9.1).
      - name: Get and set VERSION
        run: |
          TAG="${{ inputs.version || github.ref_name }}"
          echo "VERSION=${TAG#v}" >> $GITHUB_ENV

      - env:
          VERSION: ${{ env.VERSION }}
        run: npm run package $PKG_ARCH

      - uses: softprops/action-gh-release@v1
        with:
          draft: true
          discussion_category_name: "📣 Announcements"
          files: ./release-packages/*

  package-macos-amd64:
    name: x86-64 macOS build
    runs-on: macos-15-intel
    timeout-minutes: 15
    needs: npm-version
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

    steps:
      - name: Checkout repo
        uses: actions/checkout@v6

      - name: Install Node.js
        uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json

      - run: SKIP_SUBMODULE_DEPS=1 npm ci

      - name: Install nfpm
        run: |
          mkdir -p ~/.local/bin
          curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
          echo "$HOME/.local/bin" >> $GITHUB_PATH

      # The version of node-gyp we use depends on distutils but it was removed
      # in Python 3.12.  It seems to be fixed in the latest node-gyp so when we
      # next update Node we can probably remove this.  For now, install
      # setuptools since it contains distutils.
      - run: brew install python-setuptools

      - name: Download npm package
        uses: actions/download-artifact@v8
        with:
          name: npm-release-package

      - run: tar -xzf package.tar.gz
      - run: npm run release:standalone
      - run: npm run test:native

      # Strip out the v (v4.9.1 -> 4.9.1).
      - name: Get and set VERSION
        run: |
          TAG="${{ inputs.version || github.ref_name }}"
          echo "VERSION=${TAG#v}" >> $GITHUB_ENV

      - name: Build packages with nfpm
        env:
          VERSION: ${{ env.VERSION }}
        run: npm run package

      - uses: softprops/action-gh-release@v1
        with:
          draft: true
          discussion_category_name: "📣 Announcements"
          files: ./release-packages/*

  package-macos-arm64:
    name: arm64 macOS build
    runs-on: macos-latest
    timeout-minutes: 15
    needs: npm-version
    env:
      GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

    steps:
      - name: Checkout repo
        uses: actions/checkout@v6

      - name: Install Node.js
        uses: actions/setup-node@v6
        with:
          node-version-file: .node-version
          cache: npm
          cache-dependency-path: |
            package-lock.json
            test/package-lock.json

      - run: SKIP_SUBMODULE_DEPS=1 npm ci

      - name: Install nfpm
        run: |
          mkdir -p ~/.local/bin
          curl -sSfL https://github.com/goreleaser/nfpm/releases/download/v2.3.1/nfpm_2.3.1_`uname -s`_`uname -m`.tar.gz | tar -C ~/.local/bin -zxv nfpm
          echo "$HOME/.local/bin" >> $GITHUB_PATH

      # The version of node-gyp we use depends on distutils but it was removed
      # in Python 3.12.  It seems to be fixed in the latest node-gyp so when we
      # next update Node we can probably remove this.  For now, install
      # setuptools since it contains distutils.
      - run: brew install python-setuptools

      - name: Download npm package
        uses: actions/download-artifact@v8
        with:
          name: npm-release-package

      - run: tar -xzf package.tar.gz
      - run: npm run release:standalone
      - run: npm run test:native

      # Strip out the v (v4.9.1 -> 4.9.1).
      - name: Get and set VERSION
        run: |
          TAG="${{ inputs.version || github.ref_name }}"
          echo "VERSION=${TAG#v}" >> $GITHUB_ENV

      - name: Build packages with nfpm
        env:
          VERSION: ${{ env.VERSION }}
        run: npm run package

      - uses: softprops/action-gh-release@v1
        with:
          draft: true
          discussion_category_name: "📣 Announcements"
          files: ./release-packages/*

  npm-package:
    name: Upload npm package
    runs-on: ubuntu-latest
    timeout-minutes: 15
    needs: npm-version
    steps:
      - name: Download npm package
        uses: actions/download-artifact@v8
        with:
          name: npm-release-package

      - uses: softprops/action-gh-release@v1
        with:
          draft: true
          discussion_category_name: "📣 Announcements"
          files: ./package.tar.gz

  npm-version:
    name: Modify package.json version
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Download artifacts
        uses: dawidd6/action-download-artifact@v16
        id: download
        with:
          branch: ${{ github.ref }}
          workflow: build.yaml
          workflow_conclusion: completed
          name: npm-package
          check_artifacts: false
          if_no_artifact_found: fail

      - run: tar -xzf package.tar.gz

      # Strip out the v (v4.9.1 -> 4.9.1).
      - name: Get and set VERSION
        run: |
          TAG="${{ inputs.version || github.ref_name }}"
          echo "VERSION=${TAG#v}" >> $GITHUB_ENV

      - name: Modify version
        env:
          VERSION: ${{ env.VERSION }}
        run: |
          echo "Updating version in root package.json"
          npm version --prefix release "$VERSION"

          echo "Updating version in lib/vscode/product.json"
          tmp=$(mktemp)
          jq ".codeServerVersion = \"$VERSION\"" release/lib/vscode/product.json > "$tmp" && mv "$tmp" release/lib/vscode/product.json
          # Ensure it has the same permissions as before
          chmod 644 release/lib/vscode/product.json

      - run: tar -czf package.tar.gz release

      - name: Upload npm package artifact
        uses: actions/upload-artifact@v7
        with:
          name: npm-release-package
          path: ./package.tar.gz


================================================
FILE: .github/workflows/scripts.yaml
================================================
name: Script unit tests

on:
  push:
    branches:
      - main
    paths:
      - "**.sh"
      - "**.bats"
  pull_request:
    branches:
      - main
    paths:
      - "**.sh"
      - "**.bats"

permissions:
  actions: none
  checks: none
  contents: read
  deployments: none
  issues: none
  packages: none
  pull-requests: none
  repository-projects: none
  security-events: none
  statuses: none

# Cancel in-progress runs for pull requests when developers push
# additional changes, and serialize builds in branches.
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  test:
    name: Run script unit tests
    runs-on: ubuntu-latest
    # This runs on Alpine to make sure we're testing with actual sh.
    container: "alpine:3.17"
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6

      - name: Install test utilities
        run: apk add bats checkbashisms

      - name: Check Bashisms
        run: checkbashisms ./install.sh

      - name: Run script unit tests
        run: ./ci/dev/test-scripts.sh

  lint:
    name: Lint shell files
    runs-on: ubuntu-latest
    timeout-minutes: 5
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6

      - name: Install lint utilities
        run: sudo apt install shellcheck

      - name: Lint shell files
        run: ./ci/dev/lint-scripts.sh


================================================
FILE: .github/workflows/security.yaml
================================================
name: Security

on:
  push:
    branches: [main]
    paths:
      - "package.json"
  pull_request:
    paths:
      - "package.json"
  schedule:
    # Runs every Monday morning PST
    - cron: "17 15 * * 1"

# Cancel in-progress runs for pull requests when developers push additional
# changes, and serialize builds in branches.
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  audit:
    name: Audit node modules
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Install Node.js
        uses: actions/setup-node@v6
        with:
          node-version-file: .node-version

      - name: Audit npm for vulnerabilities
        run: npm audit
        if: success()

  trivy-scan-repo:
    name: Scan repo with Trivy
    permissions:
      contents: read # for actions/checkout to fetch code
      security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout repo
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Run Trivy vulnerability scanner in repo mode
        uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478
        with:
          scan-type: "fs"
          scan-ref: "."
          ignore-unfixed: true
          format: "template"
          template: "@/contrib/sarif.tpl"
          output: "trivy-repo-results.sarif"
          severity: "HIGH,CRITICAL"

      - name: Upload Trivy scan results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: "trivy-repo-results.sarif"

  codeql-analyze:
    permissions:
      actions: read # for github/codeql-action/init to get workflow details
      contents: read # for actions/checkout to fetch code
      security-events: write # for github/codeql-action/autobuild to send a status report
    name: Analyze with CodeQL
    runs-on: ubuntu-22.04

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      # Initializes the CodeQL tools for scanning.
      - name: Initialize CodeQL
        uses: github/codeql-action/init@v4
        with:
          config-file: ./.github/codeql-config.yml
          languages: javascript

      - name: Autobuild
        uses: github/codeql-action/autobuild@v4

      - name: Perform CodeQL Analysis
        uses: github/codeql-action/analyze@v4


================================================
FILE: .github/workflows/trivy-docker.yaml
================================================
name: Trivy Nightly Docker Scan

on:
  # Run scans if the workflow is modified, in order to test the
  # workflow itself. This results in some spurious notifications,
  # but seems okay for testing.
  pull_request:
    branches:
      - main
    paths:
      - .github/workflows/trivy-docker.yaml

  # Run scans against master whenever changes are merged.
  push:
    branches:
      - main
    paths:
      - .github/workflows/trivy-docker.yaml

  schedule:
    # Run at 10:15 am UTC (3:15am PT/5:15am CT)
    # Run at 0 minutes 0 hours of every day.
    - cron: "15 10 * * *"

  workflow_dispatch:

permissions:
  actions: none
  checks: none
  contents: read
  deployments: none
  issues: none
  packages: none
  pull-requests: none
  repository-projects: none
  security-events: write
  statuses: none

# Cancel in-progress runs for pull requests when developers push
# additional changes, and serialize builds in branches.
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-concurrency-to-cancel-any-in-progress-job-or-run
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}

jobs:
  trivy-scan-image:
    runs-on: ubuntu-22.04

    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Run Trivy vulnerability scanner in image mode
        uses: aquasecurity/trivy-action@97e0b3872f55f89b95b2f65b3dbab56962816478
        with:
          image-ref: "docker.io/codercom/code-server:latest"
          ignore-unfixed: true
          format: "sarif"
          output: "trivy-image-results.sarif"
          severity: "HIGH,CRITICAL"

      - name: Upload Trivy scan results to GitHub Security tab
        uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: "trivy-image-results.sarif"


================================================
FILE: .gitignore
================================================
.tsbuildinfo
.cache
/out*/
release/
release-npm-package/
release-standalone/
release-packages/
release-gcp/
release-images/
node_modules
/plugins
/lib/coder-cloud-agent
.home
coverage
**/.DS_Store

# Code packages itself here.
/lib/vscode-reh-web-*

# Failed e2e test videos are saved here
test/test-results

# Quilt's internal data.
/.pc
/patches/*.diff~


================================================
FILE: .gitmodules
================================================
[submodule "lib/vscode"]
	path = lib/vscode
	url = https://github.com/microsoft/vscode


================================================
FILE: .node-version
================================================
22.22.0


================================================
FILE: .prettierignore
================================================
lib/vscode
lib/vscode-reh-web-linux-x64
release-standalone
release-packages
release
helm-chart
test/scripts
test/e2e/extensions/test-extension
.pc
package-lock.json


================================================
FILE: .prettierrc.yaml
================================================
printWidth: 120
semi: false
trailingComma: all
arrowParens: always
singleQuote: false
useTabs: false


================================================
FILE: .tours/contributing.tour
================================================
{
  "$schema": "https://aka.ms/codetour-schema",
  "title": "Contributing",
  "steps": [
    {
      "directory": "src",
      "line": 1,
      "description": "Hello world! code-server's source code lives here in `src` (see the explorer). It's broadly arranged into browser code, Node code, and code shared between both."
    },
    {
      "file": "src/node/entry.ts",
      "line": 157,
      "description": "code-server begins execution here. CLI arguments are parsed, special flags like --help are handled, then the HTTP server is started."
    },
    {
      "file": "src/node/cli.ts",
      "line": 28,
      "description": "This describes all of the code-server CLI options and how they will be parsed."
    },
    {
      "file": "src/node/cli.ts",
      "line": 233,
      "description": "Here's the actual CLI parser."
    },
    {
      "file": "src/node/settings.ts",
      "line": 1,
      "description": "code-server maintains a settings file that is read and written here."
    },
    {
      "file": "src/node/app.ts",
      "line": 11,
      "description": "The core of code-server are HTTP and web socket servers which are created here. They provide authentication, file access, an API, and serve web-based applications like VS Code."
    },
    {
      "file": "src/node/wsRouter.ts",
      "line": 38,
      "description": "This is an analog to Express's Router that handles web socket routes."
    },
    {
      "file": "src/node/http.ts",
      "line": 1,
      "description": "This file provides various HTTP utility functions."
    },
    {
      "file": "src/node/coder_cloud.ts",
      "line": 9,
      "description": "The cloud agent spawned here provides the --link functionality."
    },
    {
      "file": "src/node/heart.ts",
      "line": 7,
      "description": "code-server's heart beats to indicate recent activity.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#heartbeat-file](https://github.com/coder/code-server/blob/main/docs/FAQ.md#heartbeat-file)"
    },
    {
      "file": "src/node/socket.ts",
      "line": 13,
      "description": "We pass sockets to child processes, however we can't pass TLS sockets so when code-server is handling TLS (via --cert) we use this to create a proxy that can be passed to the child."
    },
    {
      "directory": "src/node/routes",
      "line": 1,
      "description": "code-server's routes live here in `src/node/routes` (see the explorer)."
    },
    {
      "file": "src/node/routes/index.ts",
      "line": 123,
      "description": "The architecture of code-server allows it to be extended with applications via plugins. Each application is registered at its own route and handles requests at and below that route. Currently we have only VS Code (although it is not yet actually split out into a plugin)."
    },
    {
      "file": "src/node/plugin.ts",
      "line": 103,
      "description": "The previously mentioned plugins are loaded here."
    },
    {
      "file": "src/node/routes/apps.ts",
      "line": 12,
      "description": "This provides a list of the applications registered with code-server."
    },
    {
      "file": "src/node/routes/domainProxy.ts",
      "line": 18,
      "description": "code-server provides a built-in proxy to help in developing web-based applications. This is the code for the domain-based proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services)"
    },
    {
      "file": "src/node/routes/pathProxy.ts",
      "line": 19,
      "description": "Here is the path-based version of the proxy.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services](https://github.com/coder/code-server/blob/main/docs/FAQ.md#how-do-i-securely-access-web-services)"
    },
    {
      "file": "src/node/proxy.ts",
      "line": 4,
      "description": "Both the domain and path proxy use the single proxy instance created here."
    },
    {
      "file": "src/node/routes/health.ts",
      "line": 5,
      "description": "A simple endpoint that lets you see if code-server is up.\n\nAlso documented here: [https://github.com/coder/code-server/blob/main/docs/FAQ.md#healthz-endpoint](https://github.com/coder/code-server/blob/main/docs/FAQ.md#healthz-endpoint)"
    },
    {
      "file": "src/node/routes/login.ts",
      "line": 46,
      "description": "code-server supports a password-based login here."
    },
    {
      "file": "src/node/routes/static.ts",
      "line": 16,
      "description": "This serves static assets. Anything under the code-server directory can be fetched. Anything outside requires authentication."
    },
    {
      "file": "src/node/routes/update.ts",
      "line": 10,
      "description": "This endpoint lets you query for the latest code-server version. It's used to power the update popup you see in VS Code."
    },
    {
      "file": "src/node/routes/vscode.ts",
      "line": 15,
      "description": "This is the endpoint that serves VS Code's HTML, handles VS Code's websockets, and handles a few VS Code-specific endpoints for fetching static files."
    },
    {
      "file": "src/node/vscode.ts",
      "line": 13,
      "description": "The actual VS Code spawn and initialization is handled here. VS Code runs in a separate child process. We communicate via IPC and by passing it web sockets."
    },
    {
      "file": "src/browser/serviceWorker.ts",
      "line": 1,
      "description": "The service worker only exists to provide PWA functionality."
    },
    {
      "directory": "src/browser/pages",
      "line": 1,
      "description": "HTML, CSS, and JavaScript for each page lives in here `src/browser/pages` (see the explorer). Currently our HTML uses a simple search and replace template system with variables that {{LOOK_LIKE_THIS}}."
    },
    {
      "file": "src/browser/pages/vscode.html",
      "line": 1,
      "description": "The VS Code HTML is based off VS Code's own `workbench.html`."
    },
    {
      "directory": "src/browser/media",
      "line": 1,
      "description": "Static images and the manifest live here in `src/browser/media` (see the explorer)."
    },
    {
      "directory": "lib/vscode",
      "line": 1,
      "description": "code-server makes use of VS Code's frontend web/remote support. Most of the modifications implement the remote server since that portion of the code is closed source and not released with VS Code.\n\nWe also have a few bug fixes and have added some features (like client-side extensions). See [https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md#modifications-to-vs-code](https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md#modifications-to-vs-code) for a list.\n\nWe make an effort to keep the modifications as few as possible."
    }
  ]
}


================================================
FILE: .tours/start-development.tour
================================================
{
  "$schema": "https://aka.ms/codetour-schema",
  "title": "Start Development",
  "steps": [
    {
      "file": "package.json",
      "line": 31,
      "description": "## Commands\n\nTo start developing, make sure you have Node 16+ and the [required dependencies](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites) installed. Then, run the following commands:\n\n1. Install dependencies:\n>> npm\n\n3. Start development mode (and watch for changes):\n>> npm run watch"
    },
    {
      "file": "src/node/app.ts",
      "line": 68,
      "description": "## Visit the web server\n\nIf all goes well, you should see something like this in your terminal. code-server should be live in development mode.\n\n---\n```bash\n[2020-12-09T21:03:37.156Z] info  code-server 3.7.4 development\n[2020-12-09T21:03:37.157Z] info  Using user-data-dir ~/.local/share/code-server\n[2020-12-09T21:03:37.165Z] info  Using config file ~/.config/code-server/config.yaml\n[2020-12-09T21:03:37.165Z] info  HTTP server listening on http://127.0.0.1:8080 \n[2020-12-09T21:03:37.165Z] info    - Authentication is enabled\n[2020-12-09T21:03:37.165Z] info      - Using password from ~/.config/code-server/config.yaml\n[2020-12-09T21:03:37.165Z] info    - Not serving HTTPS\n```\n\n---\n\nIf you have the default configuration, you can access it at [http://localhost:8080](http://localhost:8080)."
    },
    {
      "file": "src/browser/pages/login.html",
      "line": 26,
      "description": "## Make a change\n\nThis is the login page, let's make a change and see it update on our web server! Perhaps change the text :)\n\n```html\n<div class=\"sub\">Modifying the login page 👨🏼‍💻</div>\n```\n\nReminder, you can likely preview at [http://localhost:8080](http://localhost:8080)"
    },
    {
      "file": "src/node/app.ts",
      "line": 62,
      "description": "## That's it!\n\n\nThat's all there is to it! When this tour ends, your terminal session may stop, but just use `npm run watch` to start developing from here on out!\n\n\nIf you haven't already, be sure to check out these resources:\n- [Tour: Contributing](command:codetour.startTourByTitle?[\"Contributing\"])\n- [Docs: FAQ.md](https://github.com/coder/code-server/blob/main/docs/FAQ.md)\n- [Docs: CONTRIBUTING.md](https://github.com/coder/code-server/blob/main/docs/CONTRIBUTING.md)\n- [Community: GitHub Discussions](https://github.com/coder/code-server/discussions)\n- [Community: Slack](https://community.coder.com)"
    }
  ]
}


================================================
FILE: CHANGELOG.md
================================================
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

<!-- Example:

## [9.99.999] - 9090-09-09

Code v99.99.999

### Changed
### Added
### Deprecated
### Removed
### Fixed
### Security

-->

## Unreleased

## [4.109.5](https://github.com/coder/code-server/releases/tag/v4.109.5) - 2026-03-02

Code v1.109.5

### Changed

- Update to Code 1.109.5

## [4.109.2](https://github.com/coder/code-server/releases/tag/v4.109.2) - 2026-02-12

Code v1.109.2

### Changed

- Update to Code 1.109.2

## [4.109.0](https://github.com/coder/code-server/releases/tag/v4.109.0) - 2026-02-12

Code v1.109.0

### Changed

- Update to Code 1.109.0

## [4.108.2](https://github.com/coder/code-server/releases/tag/v4.108.2) - 2026-01-26

Code v1.108.2

### Changed

- Update to Code 1.108.2

## [4.108.1](https://github.com/coder/code-server/releases/tag/v4.108.1) - 2026-01-16

Code v1.108.1

### Changed

- Update to Code 1.108.1

## [4.108.0](https://github.com/coder/code-server/releases/tag/v4.108.0) - 2026-01-12

Code v1.108.0

### Changed

- Update to Code 1.108.0

## [4.107.1](https://github.com/coder/code-server/releases/tag/v4.107.1) - 2026-01-09

Code v1.107.1

### Changed

- Update to Code 1.107.1

## [4.107.0](https://github.com/coder/code-server/releases/tag/v4.107.0) - 2026-12-17

Code v1.107.0

### Changed

- Update to Code 1.107.0

### Added

- New `--cookie-suffix` flag that can be used to add a suffix to the cookie when
  using the built-in password authentication. You can use this to avoid
  collisions with other instances of code-server.
- Support a new property `authorizationHeaderToken` on the extension gallery
  configuration. This will be added to marketplace requests as a bearer token
  using the `Authorization` header.

## [4.106.3](https://github.com/coder/code-server/releases/tag/v4.106.3) - 2025-12-01

Code v1.106.3

### Changed

- Update to Code 1.106.3

## [4.106.2](https://github.com/coder/code-server/releases/tag/v4.106.2) - 2025-11-19

Code v1.106.2

### Changed

- Update to Code 1.106.2

## [4.106.0](https://github.com/coder/code-server/releases/tag/v4.106.0) - 2025-11-19

Code v1.106.0

### Changed

- Update to Code 1.106.0

## [4.105.1](https://github.com/coder/code-server/releases/tag/v4.105.1) - 2025-10-20

Code v1.105.1

### Changed

- Update to Code 1.105.1

## [4.105.0](https://github.com/coder/code-server/releases/tag/v4.105.0) - 2025-10-17

Code v1.105.0

### Changed

- Update to Code 1.105.0

## [4.104.3](https://github.com/coder/code-server/releases/tag/v4.104.3) - 2025-10-07

Code v1.104.3

### Changed

- Update to Code 1.104.3.

## [4.104.2](https://github.com/coder/code-server/releases/tag/v4.104.2) - 2025-09-26

Code v1.104.2

### Changed

- Update to Code 1.104.2.

## [4.104.1](https://github.com/coder/code-server/releases/tag/v4.104.1) - 2025-09-19

Code v1.104.1

### Changed

- Update to Code 1.104.1.

## [4.104.0](https://github.com/coder/code-server/releases/tag/v4.104.0) - 2025-09-15

Code v1.104.0

### Fixed

- Fix "extension not found" errors from Open VSX when trying to install the
  latest version of an extension.

### Changed

- Update to Code 1.104.0.

## [4.103.2](https://github.com/coder/code-server/releases/tag/v4.103.2) - 2025-08-25

Code v1.103.2

### Changed

- Update to Code 1.103.2.

## [4.103.1](https://github.com/coder/code-server/releases/tag/v4.103.1) - 2025-08-15

Code v1.103.1

### Changed

- Update to Code 1.103.1.

## [4.103.0](https://github.com/coder/code-server/releases/tag/v4.103.0) - 2025-08-12

Code v1.103.0

### Changed

- Update to Code 1.103.0.

## [4.102.2](https://github.com/coder/code-server/releases/tag/v4.102.2) - 2025-07-24

Code v1.102.2

### Changed

- Update to Code 1.102.2.

## [4.102.1](https://github.com/coder/code-server/releases/tag/v4.102.1) - 2025-07-17

Code v1.102.1

### Changed

- Update to Code 1.102.1.

## [4.102.0](https://github.com/coder/code-server/releases/tag/v4.102.0) - 2025-07-16

Code v1.102.0

### Changed

- Update to Code 1.102.0.

### Added

- Custom strings can be configured using the `--i18n` flag set to a JSON
  file. This can be used for either translation (and can be used alongside
  `--locale`) or for customizing the strings. See
  [./src/node/i18n/locales/en.json](./src/node/i18n/locales/en.json) for the
  available keys.

## [4.101.2](https://github.com/coder/code-server/releases/tag/v4.101.2) - 2025-06-25

Code v1.101.2

### Changed

- Update to Code 1.101.2.

### Fixed

- Fix web views not loading due to 401 when requesting the service worker.

## [4.101.1](https://github.com/coder/code-server/releases/tag/v4.101.1) - 2025-06-20

Code v1.101.1

### Changed

- Update to Code 1.101.1.

## [4.101.0](https://github.com/coder/code-server/releases/tag/v4.101.0) - 2025-06-20

Code v1.101.0

### Changed

- Update to Code 1.101.0.

## [4.100.3](https://github.com/coder/code-server/releases/tag/v4.100.3) - 2025-06-03

Code v1.100.3

### Changed

- Update to Code 1.100.3.

## [4.100.2](https://github.com/coder/code-server/releases/tag/v4.100.2) - 2025-05-15

Code v1.100.2

### Changed

- Update to Code 1.100.2.

## [4.100.1](https://github.com/coder/code-server/releases/tag/v4.100.1) - 2025-05-13

Code v1.100.1

### Changed

- Update to Code 1.100.1.

## [4.100.0](https://github.com/coder/code-server/releases/tag/v4.100.0) - 2025-05-12

Code v1.100.0

### Added

- Trusted domains for links can now be set at run-time by configuring
  `linkProtectionTrustedDomains` in the `lib/vscode/product.json` file or via
  the `--link-protection-trusted-domains` flag.

### Changed

- Update to Code 1.100.0.
- Disable extension signature verification, which previously was skipped by
  default (the package used for verification is not available to OSS builds of
  VS Code) but now reportedly throws hard errors making it impossible to install
  extensions.

### Fixed

- Flags with repeatable options now work via the config file.

## [4.99.4](https://github.com/coder/code-server/releases/tag/v4.99.4) - 2025-05-02

Code v1.99.3

### Security

- Validate that ports in the path proxy are numbers, to prevent proxying to
  arbitrary domains.

## [4.99.3](https://github.com/coder/code-server/releases/tag/v4.99.3) - 2025-04-17

Code v1.99.3

### Added

- Added `--skip-auth-preflight` flag to let preflight requests through the
  proxy.

### Changed

- Update to Code 1.99.3.

## [4.99.2](https://github.com/coder/code-server/releases/tag/v4.99.2) - 2025-04-10

Code v1.99.2

### Changed

- Update to Code 1.99.2.

## [4.99.1](https://github.com/coder/code-server/releases/tag/v4.99.1) - 2025-04-08

Code v1.99.1

### Changed

- Update to Code 1.99.1.

## [4.99.0](https://github.com/coder/code-server/releases/tag/v4.99.0) - 2025-04-07

Code v1.99.0

### Changed

- Update to Code 1.99.0.

## [4.98.0](https://github.com/coder/code-server/releases/tag/v4.98.0) - 2025-03-07

Code v1.98.0

### Changed

- Update to Code 1.98.0.

## [4.97.2](https://github.com/coder/code-server/releases/tag/v4.96.4) - 2025-02-18

Code v1.97.2

### Added

- Added back macOS amd64 builds.

### Changed

- Update to Code 1.97.2.
- Softened dark mode login page colors.

## [4.96.4](https://github.com/coder/code-server/releases/tag/v4.96.4) - 2025-01-20

Code v1.96.4

### Changed

- Update to Code 1.96.4.

## [4.96.2](https://github.com/coder/code-server/releases/tag/v4.96.2) - 2024-12-20

Code v1.96.2

### Changed

- Update to Code 1.96.2.

## [4.96.1](https://github.com/coder/code-server/releases/tag/v4.96.1) - 2024-12-18

Code v1.96.1

### Added

- Dark color scheme for login and error pages.

### Changed

- Update to Code 1.96.1.

## [4.95.3](https://github.com/coder/code-server/releases/tag/v4.95.3) - 2024-11-18

Code v1.95.3

### Changed

- Update to Code 1.95.3.

## [4.95.2](https://github.com/coder/code-server/releases/tag/v4.95.2) - 2024-11-12

Code v1.95.2

### Changed

- Update to Code 1.95.2.

## [4.95.1](https://github.com/coder/code-server/releases/tag/v4.95.1) - 2024-11-06

Code v1.95.1

### Changed

- Update to Code 1.95.1.

## [4.93.1](https://github.com/coder/code-server/releases/tag/v4.93.1) - 2024-09-23

Code v1.93.1

### Changed

- Updated to Code 1.93.1.

### Added

- Added `--abs-proxy-base-path` flag for when code-server is not at the root.

## [4.92.2](https://github.com/coder/code-server/releases/tag/v4.92.2) - 2024-08-19

Code v1.92.2

### Breaking changes

- Dropped a patch that changed the compile target from es2022 to es2020 because
  it no longer works with the way VS Code uses static properties. This may break
  older browsers, so those browsers will either have to be updated or use an
  older version of code-server.

### Changed

- Updated to Code 1.92.2.

## [4.91.0](https://github.com/coder/code-server/releases/tag/v4.91.0) - 2024-07-10

Code v1.91.0

### Changed

- Updated to Code 1.91.0.

## [4.90.3](https://github.com/coder/code-server/releases/tag/v4.90.3) - 2024-06-21

Code v1.90.2

### Changed

- Updated to Code 1.90.2.

### Fixed

- When the log gets rotated it will no longer incorrectly be moved to a new
  directory created in the current working directory named with a date.
  Instead, the file itself is prepended with the date and kept in the same
  directory, as originally intended.

## [4.90.2](https://github.com/coder/code-server/releases/tag/v4.90.2) - 2024-06-14

Code v1.90.1

### Changed

- Updated to Code 1.90.1.

## [4.90.1](https://github.com/coder/code-server/releases/tag/v4.90.1) - 2024-06-12

Code v1.90.0

### Fixed

- Cache a call to get CPU information used in telemetry that could result in a
  lack responsiveness if it was particularly slow.

## [4.90.0](https://github.com/coder/code-server/releases/tag/v4.90.0) - 2024-06-11

Code v1.90.0

### Changed

- Updated to Code 1.90.0.
- Updated Node to 20.11.1.

### Added

- Send contents to the clipboard in the integrated terminal by piping to
  `code-server --stdin-to-clipboard` or `code-server -c`.

  You may want to make this an alias:

  ```
  alias xclip="code-server --stdin-to-clipboard"
  echo -n "hello world" | xclip
  ```

## [4.89.1](https://github.com/coder/code-server/releases/tag/v4.89.1) - 2024-04-14

Code v1.89.1

### Changed

- Updated to Code 1.89.1.

## [4.89.0](https://github.com/coder/code-server/releases/tag/v4.89.0) - 2024-04-08

Code v1.89.0

### Changed

- Updated to Code 1.89.0.

## [4.23.1](https://github.com/coder/code-server/releases/tag/v4.23.1) - 2024-04-15

Code v1.88.1

### Changed

- Updated to Code 1.88.1.

## [4.23.0](https://github.com/coder/code-server/releases/tag/v4.23.0) - 2024-04-08

Code v1.88.0

### Changed

- Updated to Code 1.88.0.
- Updated Node to 18.18.2.

### Fixed

- Fix masking the exit code when failing to install extensions on the command
  line outside the integrated terminal. Installing extensions inside the
  integrated terminal still masks the exit code and is an upstream bug.

## [4.22.1](https://github.com/coder/code-server/releases/tag/v4.22.1) - 2024-03-14

Code v1.87.2

### Changed

- Updated to Code 1.87.2.
- Enable keep-alive for proxy agent.

## [4.22.0](https://github.com/coder/code-server/releases/tag/v4.22.0) - 2024-03-03

Code v1.87.0

### Changed

- Updated to Code 1.87.0.

## [4.21.2](https://github.com/coder/code-server/releases/tag/v4.21.2) - 2024-02-28

Code v1.86.2

### Changed

- Updated to Code 1.86.2.

## [4.21.1](https://github.com/coder/code-server/releases/tag/v4.21.1) - 2024-02-09

Code v1.86.1

### Changed

- Updated to Code 1.86.1.
- Updated to Node 18.17.1.

### Added

- Docker images for Fedora and openSUSE.

## [4.21.0](https://github.com/coder/code-server/releases/tag/v4.21.0) - 2024-02-05

Code v1.86.0

### Changed

- Updated to Code 1.86.0.

## [4.20.1](https://github.com/coder/code-server/releases/tag/v4.20.1) - 2024-01-22

Code v1.85.2

### Changed

- Updated to Code 1.85.2.

### Fixed

- Query variables are no longer double-encoded when going over the path proxy.

## [4.20.0](https://github.com/coder/code-server/releases/tag/v4.20.0) - 2023-12-21

Code v1.85.1

### Added

- New flag `--disable-file-uploads` to disable uploading files to the remote by
  drag and drop and to disable opening local files via the "show local" button
  in the file open prompt. Note that you can still open local files by drag and
  dropping the file onto the editor pane.
- Added `wget` to the release image.

### Changed

- Updated to Code 1.85.1.
- The `--disable-file-downloads` flag will now disable the "show local" button
  in the file save prompt as well.
- Debian release image updated to use Bookworm.

## [4.19.1](https://github.com/coder/code-server/releases/tag/v4.19.1) - 2023-11-29

Code v1.84.2

### Fixed

- Fixed an issue where parts of the editor would not load (like the file
  explorer, source control, etc) when using a workspace file.

## [4.19.0](https://github.com/coder/code-server/releases/tag/v4.19.0) - 2023-11-18

Code v1.84.2

### Changed

- Updated to Code 1.84.2.

## [4.18.0](https://github.com/coder/code-server/releases/tag/v4.18.0) - 2023-10-20

Code v1.83.1

### Changed

- Updated to Code 1.83.1.

## [4.17.1](https://github.com/coder/code-server/releases/tag/v4.17.1) - 2023-09-29

Code v1.82.2

### Fixed

- Make secret storage persistent. For example, logging in with GitHub should
  persist between browser refreshes and code-server restarts.
- Issues with argon2 on arm builds should be fixed now.

## [4.17.0](https://github.com/coder/code-server/releases/tag/v4.17.0) - 2023-09-22

Code v1.82.2

### Added

- Japanese locale.
- `CODE_SERVER_HOST` environment variable.

### Changed

- Update to Code 1.82.2. This includes an update to Node 18, which also means
  that the minimum glibc is now 2.28. If you need to maintain a lower glibc then
  you can take a version of Node 18 that is compiled with a lower glibc and use
  that to build code-server (or at a minimum rebuild the native modules).
- Display paths to config files in full rather than abbreviated. If you have
  trouble with the password not working please update and make sure the
  displayed config paths are what you expect.

### Fixed

- Fix some dependency issues for the standalone arm64 and armv7l releases. If
  you had issues with missing or failing modules please try these new builds.

## [4.16.1](https://github.com/coder/code-server/releases/tag/v4.16.1) - 2023-07-31

Code v1.80.2

### Changed

- Updated to Code 1.80.2.

## [4.16.0](https://github.com/coder/code-server/releases/tag/v4.16.0) - 2023-07-28

Code v1.80.1

### Added

- `--disable-proxy` flag. This disables the domain and path proxies but it does
  not disable the ports panel in Code. That can be disabled by using
  `remote.autoForwardPorts=false` in your settings.

## [4.15.0](https://github.com/coder/code-server/releases/tag/v4.15.0) - 2023-07-21

Code v1.80.1

### Changed

- Updated to Code 1.80.1.

### Added

- `--trusted-origin` flag for specifying origins that you trust but do not
  control (for example a reverse proxy).

Code v1.79.2

## [4.14.1](https://github.com/coder/code-server/releases/tag/v4.14.1) - 2023-06-26

Code v1.79.2

### Security

- Remove extra write permissions on the Node binary bundled with the linux-amd64
  tarball. If you extract the tar without a umask this could mean the Node
  binary would be unexpectedly writable.

### Fixed

- Inability to launch multiple instances of code-server for different users.

### Added

- `--session-socket` CLI flag to configure the location of the session socket.
  By default it will be placed in `<user data dir>/code-server-ipc.sock`.

## [4.14.0](https://github.com/coder/code-server/releases/tag/v4.14.0) - 2023-06-16

Code v1.79.2

### Added

- `--domain-proxy` now supports `{{port}}` and `{{host}}` template variables.

### Changed

- Updated to Code 1.79.2
- Files opened from an external terminal will now open in the most closely
  related window rather than in the last opened window.

## [4.13.0](https://github.com/coder/code-server/releases/tag/v4.13.0) - 2023-05-19

Code v1.78.2

### Changed

- Updated to Code 1.78.2.

### Fixed

- Proxying files that contain non-ASCII characters.
- Origin check when X-Forwarded-Host contains comma-separated hosts.

## [4.12.0](https://github.com/coder/code-server/releases/tag/v4.12.0) - 2023-04-21

Code v1.77.3

### Changed

- Updated to Code 1.77.3
- Ports panel will use domain-based proxy (instead of the default path-based
  proxy) when set via --proxy-domain.
- Apply --app-name to the PWA title.

### Added

- Thai translation for login page.
- Debug logs around the origin security check. If you are getting forbidden
  errors on web sockets please run code-server with `--log debug` to see why the
  requests are being blocked.

## [4.11.0](https://github.com/coder/code-server/releases/tag/v4.11.0) - 2023-03-16

Code v1.76.1

### Changed

- Updated to Code 1.76.1

## [4.10.1](https://github.com/coder/code-server/releases/tag/v4.10.1) - 2023-03-04

Code v1.75.1

### Security

Added an origin check to web sockets to prevent cross-site hijacking attacks on
users using older or niche browser that do not support SameSite cookies and
attacks across sub-domains that share the same root domain.

The check requires the host header to be set so if you use a reverse proxy
ensure it forwards that information otherwise web sockets will be blocked.

## [4.10.0](https://github.com/coder/code-server/releases/tag/v4.10.0) - 2023-02-15

Code v1.75.1

### Changed

- Updated to Code 1.75.1

### Removed

- Removed `--link` (was deprecated over thirteen months ago in 4.0.1).

## [4.9.1](https://github.com/coder/code-server/releases/tag/v4.9.1) - 2022-12-15

Code v1.73.1

### Changed

- Updated a couple steps in the build and release process to ensure we're using
  `npm` and `yarn` consistently depending on the step.

### Fixed

- Fixed an issue with code-server version not displaying in the Help > About window.
- Fixed terminal not loading on macOS clients.

## [4.9.0](https://github.com/coder/code-server/releases/tag/v4.9.0) - 2022-12-06

Code v1.73.1

### Changed

- Upgraded to Code 1.73.1

### Added

- `/security.txt` added as a route with info on our security policy information thanks to @ghuntley

### Fixed

- Installing on majaro images should now work thanks to @MrPeacockNLB for
  adding the `--noconfirm` flag in `install.sh`

### Known Issues

- `--cert` on Ubuntu 22.04: OpenSSL v3 is used which breaks `pem` meaning the
  `--cert` feature will not work. [Reference](https://github.com/adobe/fetch/pull/318#issuecomment-1306070259)

## [4.8.3](https://github.com/coder/code-server/releases/tag/v4.8.3) - 2022-11-07

Code v1.72.1

### Added

- install script now supports arch-like (i.e. manjaro, endeavourous, etc.)
  architectures

### Changed

- Updated text in the Getting Started page.

## [4.8.2](https://github.com/coder/code-server/releases/tag/v4.8.2) - 2022-11-02

Code v1.72.1

### Added

- New text in the Getting Started page with info about
  `coder/coder`. This is enabled by default but can be disabled by passing the CLI
  flag `--disable-getting-started-override` or setting
  `CS_DISABLE_GETTING_STARTED_OVERRIDE=1` or
  `CS_DISABLE_GETTING_STARTED_OVERRIDE=true`.

## [4.8.1](https://github.com/coder/code-server/releases/tag/v4.8.1) - 2022-10-28

Code v1.72.1

### Fixed

- Fixed CSP error introduced in 4.8.0 that caused issues with webviews and most
  extensions.

## [4.8.0](https://github.com/coder/code-server/releases/tag/v4.8.0) - 2022-10-24

Code v1.72.1

### Added

- Support for the Ports panel which leverages code-server's built-in proxy. It
  also uses `VSCODE_PROXY_URI` where `{{port}}` is replace when forwarding a port.
  Example: `VSCODE_PROXY_URI=https://{{port}}.kyle.dev` would forward an
  application running on localhost:3000 to https://3000.kyle.dev
- Support for `--disable-workspace-trust` CLI flag
- Support for `--goto` flag to open file @ line:column
- Added Ubuntu-based images for Docker releases. If you run into issues with
  `PATH` being overwritten in Docker please try the Ubuntu image as this is a
  problem in the Debian base image.

### Changed

- Updated Code to 1.72.1

### Fixed

- Enabled `BROWSER` environment variable
- Patched `asExternalUri` to work so now extensions run inside code-server can use it

## [4.7.1](https://github.com/coder/code-server/releases/tag/v4.7.1) - 2022-09-30

Code v1.71.2

### Changed

- Updated Code to 1.71.2

### Fixed

- Fixed install script not upgrading code-server when already installed on RPM-based machines
- Fixed install script failing to gain root permissions on FreeBSD

## [4.7.0](https://github.com/coder/code-server/releases/tag/v4.7.0) - 2022-09-09

Code v1.71.0

### Changed

- Updated Code to 1.71.0

### Removed

- Dropped heartbeat patch because it was implemented upstream

### Fixed

- Add flags --unsafe-perm --legacy-peer-deps in `npm-postinstall.sh` which ensures installing with npm works correctly

## [4.6.1](https://github.com/coder/code-server/releases/tag/v4.6.1) - 2022-09-31

Code v1.70.2

### Changed

- Updated Code to 1.70.2
- Updated `argon2` to 0.29.0 which should fix issues on FreeBSD
- Updated docs to suggest using `npm` instead of `yarn`

### Removed

- Dropped database migration patch affected to 4.0.2 versions and earlier.

### Fixed

- Fixed preservation of `process.execArgv` which means you can pass `--prof` to profile code-server

## [4.6.0](https://github.com/coder/code-server/releases/tag/v4.6.0) - 2022-08-17

Code v1.70.1

### Changed

- Updated Code to 1.70.1.

### Added

- Added a heartbeat to sockets. This should prevent them from getting closed by
  reverse proxy timeouts when idle like NGINX's default 60-second timeout.

### Fixed

- Fixed logout option appearing even when authentication is disabled.

## [4.5.2](https://github.com/coder/code-server/releases/tag/v4.5.2) - 2022-08-15

Code v1.68.1

### Security

- Fixed the proxy route not performing authentication. For example if you were
  to run a development HTTP server using `python -m http.server 8000` then it
  would be accessible at `my.domain/proxy/8000/` without any authentication.

  If all of the following apply to you please update as soon as possible:
  - You run code-server with the built-in password authentication.
  - You run unprotected HTTP services on ports accessible by code-server.

### Changed

- Invoking `code-server` in the integrated terminal will now use the script that
  comes with upstream Code. This means flags like `--wait` will be
  automatically supported now. However the upstream script only has the ability
  to interact with the running code-server and cannot spawn new instances. If
  you need to spawn a new code-server from the integrated terminal please
  specify the full path to code-server's usual script (for example
  `/usr/bin/code-server`).

### Fixed

- Invoking `code-server` in the integrated terminal will now work instead of
  erroring about not finding Node.

## [4.5.1](https://github.com/coder/code-server/releases/tag/v4.5.1) - 2022-07-18

Code v1.68.1

### Changed

- We now use `release/v<0.0.0>` for the release branch name so it doesn't
  conflict with the tag name
- Added `.prettierignore` to ignore formatting files in `lib/vscode`

### Added

- Allow more comprehensive affinity config in Helm chart
- Added custom message in Homebrew PR to make sure code-server maintainers are
  tagged
- Allow setting `priorityClassName` via Helm chart
- Added troubleshooting docs to `CONTRIBUTING.md`

### Fixed

- Removed default memory limit which was set via `NODE_OPTIONS`
- Changed output in pipe to make it easier to debug code-server when doing live
  edits
- Fixed display-language patch to use correct path which broke in 4.5.0
- Fixed multiple code-server windows opening when using the code-server CLI in
  the Integrated Terminal
- Fixed Integrated Terminal not working when web base was not the root path

### Security

- Updated `glob-parent` version in dependencies

## [4.5.0](https://github.com/coder/code-server/releases/tag/v4.5.0) - 2022-06-29

Code v1.68.1

### Changed

- Updated codecov to use codecov uploader
- Moved integration tests to Jest
- Fixed docker release to only download .deb
- Upgraded to Code 1.68.1
- Install `nfpm` from GitHub
- Upgraded to TypeScript 4.6

### Added

- Added tests for `open`, `isWsl`, `handlePasswordValidation`
- Provided alternate image registry to dockerhub
- Allowed users to have scripts run on container with `ENTRYPOINTD` environment
  variable

### Fixed

- Fixed open CLI command to work on macOS

## [4.4.0](https://github.com/coder/code-server/releases/tag/v4.4.0) - 2022-05-06

Code v1.66.2

### Changed

- Refactored methods in `Heart` class and made `Heart.beat()` async to make
  testing easier.
- Upgraded to Code 1.66.2.

### Added

- Added back telemetry patch which was removed in the Code reachitecture.
- Added support to use `true` for `CS_DISABLE_FILE_DOWNLOADS` environment
  variable. This means you can disable file downloads by setting
  `CS_DISABLE_FILE_DOWNLOADS` to `true` or `1`.
- Added tests for `Heart` class.

### Fixed

- Fixed installation issue in AUR after LICENSE rename.
- Fixed issue with listening on IPv6 addresses.
- Fixed issue with Docker publish action not being able to find artifacts. Now
  it downloads the release assets from the release.

## [4.3.0](https://github.com/coder/code-server/releases/tag/v4.3.0) - 2022-04-14

Code v1.65.2

### Changed

- Excluded .deb files from release Docker image which drops the compressed and
  uncompressed size by 58% and 34%.
- Upgraded to Code 1.65.2.

### Added

- Added a new CLI flag called `--disable-file-downloads` which allows you to
  disable the "Download..." option that shows in the UI when right-clicking on a
  file. This can also set by running `CS_DISABLE_FILE_DOWNLOADS=1`.
- Aligned the dependencies for binary and npm release artifacts.

### Fixed

- Fixed the code-server version from not displaying in the Help > About dialog.
- Fixed issues with the TypeScript and JavaScript Language Features Extension
  failing to activate.
- Fixed missing files in ipynb extension.
- Fixed the homebrew release workflow.
- Fixed the Docker release workflow from not always publishing version tags.

## [4.2.0](https://github.com/coder/code-server/releases/tag/v4.2.0) - 2022-03-22

Code v1.64.2

### Added

- Added tests for `handleArgsSocketCatchError`, `setDefaults` and
  `optionDescriptions`.

### Changed

- We switched from using the fork `coder/vscode` to a submodule of
  `microsoft/vscode` + patches managed by `quilt` for how Code sits inside the
  code-server codebase.
- Upgraded to Code 1.64.2.

### Fixed

- Update popup notification through `--disable-update-check` is now fixed.
- Fixed PWA icons not loading on iPad
- Fixed the homebrew release process. Our `cdrci` bot should now automatically
  update the version as part of the release pipeline.
- Fixed titleBar color setting being ignored in PWA.

### Security

- Updated to `minimist-list`.
- Updated `cloud-agent` to `v0.2.4` which uses `nhooyr.io/webscoket` `v1.8.7`.

## [4.1.0](https://github.com/coder/code-server/releases/tag/v4.1.0) - 2022-03-03

Code v1.63.0

### Added

- Support for injecting GitHub token into Code so extensions can make use of it.
  This can be done with the `GITHUB_TOKEN` environment variable or `github-auth`
  in the config file.
- New flag `--socket-mode` allows setting the mode (file permissions) of the
  socket created when using `--socket`.
- The version of Code bundled with code-server now appears when using the
  `--version` flag. For example: `4.0.2 5cdfe74686aa73e023f8354a9a6014eb30caa7dd with Code 1.63.0`.
  If you have been parsing this flag for the version you might want to use
  `--version --json` instead as doing that will be more stable.

### Changed

- The workspace or folder passed on the CLI will now use the same redirect
  method that the last opened workspace or folder uses. This means if you use
  something like `code-server /path/to/dir` you will now get a query parameter
  added (like so: `my-domain.tld?folder=/path/to/dir`), making it easier to edit
  by hand and making it consistent with the last opened and menu open behaviors.
- The folder/workspace query parameter no longer has encoded slashes, making
  them more readable and editable by hand. This was only affecting the last
  opened behavior, not opens from the menu.

### Fixed

- Fix web sockets not connecting when using `--cert`.
- Prevent workspace state collisions when opening a workspace that shares the
  same file path with another workspace on a different machine that shares the
  same domain. This was causing files opened in one workspace to be "re-"opened
  in the other workspace when the other workspace is opened.
- Pin the Express version which should make installing from npm work again.
- Propagate signals to code-server in the Docker image which means it should
  stop more quickly and gracefully.
- Fix missing argon binaries in the standalone releases on arm machines.

## [4.0.2](https://github.com/coder/code-server/releases/tag/v4.0.2) - 2022-01-27

Code v1.63.0

### Fixed

- Unset the `BROWSER` environment variable. This fixes applications that hard
  exit when trying to spawn the helper script `BROWSER` points to because the
  file is missing. While we do include the script now we are leaving the
  variable omitted because the script does not work yet.

## [4.0.1](https://github.com/coder/code-server/releases/tag/v4.0.1) - 2022-01-04

Code v1.63.0

code-server has been rebased on upstream's newly open-sourced server
implementation (#4414).

### Changed

- Web socket compression has been made the default (when supported). This means
  the `--enable` flag will no longer take `permessage-deflate` as an option.
- The static endpoint can no longer reach outside code-server. However the
  vscode-remote-resource endpoint still can.
- OpenVSX has been made the default marketplace.
- The last opened folder/workspace is no longer stored separately in the
  settings file (we rely on the already-existing query object instead).
- The marketplace override environment variables `SERVICE_URL` and `ITEM_URL`
  have been replaced with a single `EXTENSIONS_GALLERY` variable that
  corresponds to `extensionsGallery` in Code's `product.json`.

### Added

- `VSCODE_PROXY_URI` env var for use in the terminal and extensions.

### Removed

- Extra extension directories have been removed. The `--extra-extensions-dir`
  and `--extra-builtin-extensions-dir` flags will no longer be accepted.
- The `--install-source` flag has been removed.

### Deprecated

- `--link` is now deprecated (#4562).

### Security

- We fixed a XSS vulnerability by escaping HTML from messages in the error page (#4430).

## [3.12.0](https://github.com/coder/code-server/releases/tag/v3.12.0) - 2021-09-15

Code v1.60.0

### Changed

- Upgrade Code to 1.60.0.

### Fixed

- Fix logout when using a base path (#3608).

## [3.11.1](https://github.com/coder/code-server/releases/tag/v3.11.1) - 2021-08-06

Undocumented (see releases page).

## [3.11.0](https://github.com/coder/code-server/releases/tag/v3.11.0) - 2021-06-14

Undocumented (see releases page).

## [3.10.2](https://github.com/coder/code-server/releases/tag/v3.10.2) - 2021-05-21

Code v1.56.1

### Added

- Support `extraInitContainers` in helm chart values (#3393).

### Changed

- Change `extraContainers` to support templating in helm chart (#3393).

### Fixed

- Fix "Open Folder" on welcome page (#3437).

## [3.10.1](https://github.com/coder/code-server/releases/tag/v3.10.1) - 2021-05-17

Code v1.56.1

### Fixed

- Check the logged user instead of $USER (#3330).
- Fix broken node_modules.asar symlink in npm package (#3355).
- Update cloud agent to fix version issue (#3342).

### Changed

- Use xdgBasedir.runtime instead of tmp (#3304).

## [3.10.0](https://github.com/coder/code-server/releases/tag/v3.10.0) - 2021-05-10

Code v1.56.0

### Changed

- Update to Code 1.56.0 (#3269).
- Minor connections refactor (#3178). Improves connection stability.
- Use ptyHostService (#3308). This brings us closer to upstream Code.

### Added

- Add flag for toggling permessage-deflate (#3286). The default is off so
  compression will no longer be used by default. Use the --enable flag to
  toggle it back on.

### Fixed

- Make rate limiter not count against successful logins (#3141).
- Refactor logout (#3277). This fixes logging out in some scenarios.
- Make sure directories exist (#3309). This fixes some errors on startup.

### Security

- Update dependencies with CVEs (#3223).

## Previous versions

This was added with `3.10.0`, which means any previous versions are not
documented in the changelog.

To see those, please visit the [Releases page](https://github.com/coder/code-server/releases).


================================================
FILE: LICENSE
================================================
The MIT License

Copyright (c) 2019 Coder Technologies Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: ThirdPartyNotices.txt
================================================
code-server

THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
Do Not Translate or Localize

1.	Microsoft/vscode version 1.47.0 (https://github.com/Microsoft/vscode)

%% Microsoft/vscode NOTICES AND INFORMATION BEGIN HERE
=========================================
MIT License 


Copyright (c) 2015 - present Microsoft Corporation 


Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 


The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 


THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  

================================================
FILE: ci/Caddyfile
================================================
{
	admin    localhost:4444
}
:8000 {
	@portLocalhost path_regexp port ^/([0-9]+)\/ide
        handle @portLocalhost {
		uri strip_prefix {re.port.1}/ide
                reverse_proxy localhost:{re.port.1}
        }

	handle {
                respond "Bad hostname" 400
        }

}


================================================
FILE: ci/README.md
================================================
# ci

This directory contains scripts used for code-server's continuous integration infrastructure.

Some of these scripts contain more detailed documentation and options
in header comments.

Any file or directory in this subdirectory should be documented here.

- [./ci/lib.sh](./lib.sh)
  - Contains code duplicated across these scripts.

## dev

This directory contains scripts used for the development of code-server.

- [./ci/dev/image](./dev/image)
  - See [./docs/CONTRIBUTING.md](../docs/CONTRIBUTING.md) for docs on the development container.
- [./ci/dev/fmt.sh](./dev/fmt.sh) (`npm run fmt`)
  - Runs formatters.
- [./ci/dev/lint.sh](./dev/lint.sh) (`npm run lint`)
  - Runs linters.
- [./ci/dev/test-unit.sh](./dev/test-unit.sh) (`npm run test:unit`)
  - Runs unit tests.
- [./ci/dev/test-e2e.sh](./dev/test-e2e.sh) (`npm run test:e2e`)
  - Runs end-to-end tests.
- [./ci/dev/watch.ts](./dev/watch.ts) (`npm run watch`)
  - Starts a process to build and launch code-server and restart on any code changes.
  - Example usage in [./docs/CONTRIBUTING.md](../docs/CONTRIBUTING.md).
- [./ci/dev/gen_icons.sh](./dev/gen_icons.sh) (`npm run icons`)
  - Generates the various icons from a single `.svg` favicon in
    `src/browser/media/favicon.svg`.
  - Requires [imagemagick](https://imagemagick.org/index.php)

## build

This directory contains the scripts used to build and release code-server.
You can disable minification by setting `MINIFY=`.

- [./ci/build/build-code-server.sh](./build/build-code-server.sh) (`npm run build`)
  - Builds code-server into `./out` and bundles the frontend into `./dist`.
- [./ci/build/build-vscode.sh](./build/build-vscode.sh) (`npm run build:vscode`)
  - Builds vscode into `./lib/vscode/out-vscode`.
- [./ci/build/build-release.sh](./build/build-release.sh) (`npm run release`)
  - Bundles the output of the above two scripts into a single node module at `./release`.
- [./ci/build/clean.sh](./build/clean.sh) (`npm run clean`)
  - Removes all build artifacts.
  - Useful to do a clean build.
- [./ci/build/code-server.sh](./build/code-server.sh)
  - Copied into standalone releases to run code-server with the bundled node binary.
- [./ci/build/test-standalone-release.sh](./build/test-standalone-release.sh) (`npm run test:standalone-release`)
  - Ensures code-server in the `./release-standalone` directory works by installing an extension.
- [./ci/build/build-packages.sh](./build/build-packages.sh) (`npm run package`)
  - Packages `./release-standalone` into a `.tar.gz` archive in `./release-packages`.
  - If on linux, [nfpm](https://github.com/goreleaser/nfpm) is used to generate `.deb` and `.rpm`.
- [./ci/build/nfpm.yaml](./build/nfpm.yaml)
  - Used to configure [nfpm](https://github.com/goreleaser/nfpm) to generate `.deb` and `.rpm`.
- [./ci/build/code-server-nfpm.sh](./build/code-server-nfpm.sh)
  - Entrypoint script for code-server for `.deb` and `.rpm`.
- [./ci/build/code-server.service](./build/code-server.service)
  - systemd user service packaged into the `.deb` and `.rpm`.
- [./ci/build/release-github-draft.sh](./build/release-github-draft.sh) (`npm run release:github-draft`)
  - Uses [gh](https://github.com/cli/cli) to create a draft release with a template description.
- [./ci/build/release-github-assets.sh](./build/release-github-assets.sh) (`npm run release:github-assets`)
  - Downloads the release-package artifacts for the current commit from CI.
  - Uses [gh](https://github.com/cli/cli) to upload the artifacts to the release
    specified in `package.json`.
- [./ci/build/npm-postinstall.sh](./build/npm-postinstall.sh)
  - Post install script for the npm package.
  - Bundled by`npm run release`.

## release-image

This directory contains the release docker container image.

- [./ci/steps/build-docker-buildx-push.sh](./steps/docker-buildx-push.sh)
  - Builds the release containers with tags `codercom/code-server-$ARCH:$VERSION` for amd64 and arm64 with `docker buildx` and pushes them.
  - Assumes debian releases are ready in `./release-packages`.

## images

This directory contains the images for CI.

## steps

This directory contains the scripts used in CI.
Helps avoid clobbering the CI configuration.

- [./steps/fmt.sh](./steps/fmt.sh)
  - Runs `npm run fmt`.
- [./steps/lint.sh](./steps/lint.sh)
  - Runs `npm run lint`.
- [./steps/test-unit.sh](./steps/test-unit.sh)
  - Runs `npm run test:unit`.
- [./steps/test-integration.sh](./steps/test-integration.sh)
  - Runs `npm run test:integration`.
- [./steps/test-e2e.sh](./steps/test-e2e.sh)
  - Runs `npm run test:e2e`.
- [./steps/release.sh](./steps/release.sh)
  - Runs the release process.
  - Generates the npm package at `./release`.
- [./steps/release-packages.sh](./steps/release-packages.sh)
  - Takes the output of the previous script and generates a standalone release and
    release packages into `./release-packages`.
- [./steps/publish-npm.sh](./steps/publish-npm.sh)
  - Grabs the `npm-package` release artifact for the current commit and publishes it on npm.
- [./steps/docker-buildx-push.sh](./steps/docker-buildx-push.sh)
  - Builds the docker image and then pushes it.
- [./steps/push-docker-manifest.sh](./steps/push-docker-manifest.sh)
  - Loads all images in `./release-images` and then builds and pushes a multi architecture
    docker manifest for the amd64 and arm64 images to `codercom/code-server:$VERSION` and
    `codercom/code-server:latest`.


================================================
FILE: ci/build/build-code-server.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

# Builds code-server into out and the frontend into dist.

main() {
  cd "$(dirname "${0}")/../.."

  tsc

  # If out/node/entry.js does not already have the shebang,
  # we make sure to add it and make it executable.
  if ! grep -q -m1 "^#!/usr/bin/env node" out/node/entry.js; then
    sed -i.bak "1s;^;#!/usr/bin/env node\n;" out/node/entry.js && rm out/node/entry.js.bak
    chmod +x out/node/entry.js
  fi
}

main "$@"


================================================
FILE: ci/build/build-lib.sh
================================================
#!/usr/bin/env bash

# This is a library which contains functions used inside ci/build
#
# We separated it into it's own file so that we could easily unit test
# these functions and helpers.

# On some CPU architectures (notably node/uname "armv7l", default on Raspberry Pis),
# different package managers have different labels for the same CPU (deb=armhf, rpm=armhfp).
# This function returns the overriden arch on platforms
# with alternate labels, or the same arch otherwise.
get_nfpm_arch() {
  local PKG_FORMAT="${1:-}"
  local ARCH="${2:-}"

  case "$ARCH" in
    armv7l)
      if [ "$PKG_FORMAT" = "deb" ]; then
        echo armhf
      elif [ "$PKG_FORMAT" = "rpm" ]; then
        echo armhfp
      fi
      ;;
    *)
      echo "$ARCH"
      ;;
  esac
}


================================================
FILE: ci/build/build-packages.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

# Given a platform-specific release found in ./release-standalone, generate an
# compressed archives and bundles (as appropriate for the platform) named after
# the platform's architecture and OS and place them in ./release-packages and
# ./release-gcp.

main() {
  cd "$(dirname "${0}")/../.."
  source ./ci/lib.sh
  source ./ci/build/build-lib.sh

  # Allow us to override architecture
  # we use this for our Linux ARM64 cross compile builds
  if [ "$#" -eq 1 ] && [ "$1" ]; then
    ARCH=$1
  fi

  mkdir -p release-packages

  release_archive

  if [[ $OS == "linux" ]]; then
    release_nfpm
  fi
}

release_archive() {
  local release_name="code-server-$VERSION-$OS-$ARCH"
  if [[ $OS == "linux" ]]; then
    tar -czf "release-packages/$release_name.tar.gz" --owner=0 --group=0 --transform "s/^\.\/release-standalone/$release_name/" ./release-standalone
  else
    tar -czf "release-packages/$release_name.tar.gz" -s "/^release-standalone/$release_name/" release-standalone
  fi

  echo "done (release-packages/$release_name)"

  release_gcp
}

release_gcp() {
  mkdir -p "release-gcp/$VERSION"
  cp "release-packages/$release_name.tar.gz" "./release-gcp/$VERSION/$OS-$ARCH.tar.gz"
  mkdir -p "release-gcp/latest"
  cp "./release-packages/$release_name.tar.gz" "./release-gcp/latest/$OS-$ARCH.tar.gz"
}

# Generates deb and rpm packages.
release_nfpm() {
  local nfpm_config

  export NFPM_ARCH

  PKG_FORMAT="deb"
  NFPM_ARCH="$(get_nfpm_arch $PKG_FORMAT "$ARCH")"
  nfpm_config="$(envsubst < ./ci/build/nfpm.yaml)"
  echo "Building deb"
  echo "$nfpm_config" | head --lines=4
  nfpm pkg -f <(echo "$nfpm_config") --target "release-packages/code-server_${VERSION}_${NFPM_ARCH}.deb"

  PKG_FORMAT="rpm"
  NFPM_ARCH="$(get_nfpm_arch $PKG_FORMAT "$ARCH")"
  nfpm_config="$(envsubst < ./ci/build/nfpm.yaml)"
  echo "Building rpm"
  echo "$nfpm_config" | head --lines=4
  nfpm pkg -f <(echo "$nfpm_config") --target "release-packages/code-server-$VERSION-$NFPM_ARCH.rpm"
}

main "$@"


================================================
FILE: ci/build/build-release.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

# Once both code-server and VS Code have been built, use this script to copy
# them into a single directory (./release), prepare the package.json and
# product.json, and add shrinkwraps.  This results in a generic NPM package that
# we published to NPM and also use to compile platform-specific packages.

# MINIFY controls whether minified VS Code is bundled. It must match the value
# used when VS Code was built.
MINIFY="${MINIFY-true}"

# node_modules are not copied by default.  Set KEEP_MODULES=1 to copy them.
KEEP_MODULES="${KEEP_MODULES-0}"

main() {
  cd "$(dirname "${0}")/../.."

  source ./ci/lib.sh

  VSCODE_SRC_PATH="lib/vscode"
  VSCODE_OUT_PATH="$RELEASE_PATH/lib/vscode"

  create_shrinkwraps

  mkdir -p "$RELEASE_PATH"

  bundle_code_server
  bundle_vscode

  rsync ./docs/README.md "$RELEASE_PATH"
  rsync LICENSE "$RELEASE_PATH"
  rsync ./lib/vscode/ThirdPartyNotices.txt "$RELEASE_PATH"
}

bundle_code_server() {
  rsync out "$RELEASE_PATH"

  # For source maps and images.
  mkdir -p "$RELEASE_PATH/src/browser"
  rsync src/browser/media/ "$RELEASE_PATH/src/browser/media"
  mkdir -p "$RELEASE_PATH/src/browser/pages"
  rsync src/browser/pages/*.html "$RELEASE_PATH/src/browser/pages"
  rsync src/browser/pages/*.css "$RELEASE_PATH/src/browser/pages"
  rsync src/browser/robots.txt "$RELEASE_PATH/src/browser"

  # Adds the commit to package.json
  jq --slurp '(.[0] | del(.scripts,.jest,.devDependencies)) * .[1]' package.json <(
    cat << EOF
  {
    "commit": "$(git rev-parse HEAD)",
    "scripts": {
      "postinstall": "sh ./postinstall.sh"
    }
  }
EOF
  ) > "$RELEASE_PATH/package.json"
  mv npm-shrinkwrap.json "$RELEASE_PATH"

  rsync ci/build/npm-postinstall.sh "$RELEASE_PATH/postinstall.sh"

  if [ "$KEEP_MODULES" = 1 ]; then
    rsync node_modules/ "$RELEASE_PATH/node_modules"
  fi
}

bundle_vscode() {
  mkdir -p "$VSCODE_OUT_PATH"

  local rsync_opts=()
  if [[ ${DEBUG-} = 1 ]]; then
    rsync_opts+=(-vh)
  fi

  # Some extensions have a .gitignore which excludes their built source from the
  # npm package so exclude any .gitignore files.
  rsync_opts+=(--exclude .gitignore)

  # Exclude Node as we will add it ourselves for the standalone and will not
  # need it for the npm package.
  rsync_opts+=(--exclude /node)

  # Exclude Node modules.
  if [[ $KEEP_MODULES = 0 ]]; then
    rsync_opts+=(--exclude node_modules)
  fi

  rsync "${rsync_opts[@]}" ./lib/vscode-reh-web-*/ "$VSCODE_OUT_PATH"

  # Merge the package.json for the web/remote server so we can include
  # dependencies, since we want to ship this via NPM.
  jq --slurp '.[0] * .[1]' \
    "$VSCODE_SRC_PATH/remote/package.json" \
    "$VSCODE_OUT_PATH/package.json" > "$VSCODE_OUT_PATH/package.json.merged"
  mv "$VSCODE_OUT_PATH/package.json.merged" "$VSCODE_OUT_PATH/package.json"
  cp "$VSCODE_SRC_PATH/remote/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/npm-shrinkwrap.json"

  # Include global extension dependencies as well.
  rsync "$VSCODE_SRC_PATH/extensions/package.json" "$VSCODE_OUT_PATH/extensions/package.json"
  cp "$VSCODE_SRC_PATH/extensions/npm-shrinkwrap.json" "$VSCODE_OUT_PATH/extensions/npm-shrinkwrap.json"
  rsync "$VSCODE_SRC_PATH/extensions/postinstall.mjs" "$VSCODE_OUT_PATH/extensions/postinstall.mjs"
}

create_shrinkwraps() {
  # package-lock.json files (used to ensure deterministic versions of
  # dependencies) are not packaged when publishing to the NPM registry.
  #
  # To ensure deterministic dependency versions (even when code-server is
  # installed with NPM), we create an npm-shrinkwrap.json file from the
  # currently installed node_modules. This ensures the versions used from
  # development (that the package-lock.json guarantees) are also the ones
  # installed by end-users.  These will include devDependencies, but those will
  # be ignored when installing globally (for code-server), and because we use
  # --omit=dev (for VS Code).

  # We first generate the shrinkwrap file for code-server itself - which is the
  # current directory.
  cp package-lock.json package-lock.json.temp
  npm shrinkwrap
  mv package-lock.json.temp package-lock.json

  # Then the shrinkwrap files for the bundled VS Code.
  pushd "$VSCODE_SRC_PATH/remote/"
  cp package-lock.json package-lock.json.temp
  npm shrinkwrap
  mv package-lock.json.temp package-lock.json
  popd

  pushd "$VSCODE_SRC_PATH/extensions/"
  cp package-lock.json package-lock.json.temp
  npm shrinkwrap
  mv package-lock.json.temp package-lock.json
  popd
}

main "$@"


================================================
FILE: ci/build/build-standalone-release.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

# Once we have an NPM package, use this script to copy it to a separate
# directory (./release-standalone) and install the dependencies.  This new
# directory can then be packaged as a platform-specific release.

main() {
  cd "$(dirname "${0}")/../.."

  source ./ci/lib.sh

  rsync "$RELEASE_PATH/" "$RELEASE_PATH-standalone"
  RELEASE_PATH+=-standalone

  # Package managers may shim their own "node" wrapper into the PATH, so run
  # node and ask it for its true path.
  local node_path
  node_path="$(node -p process.execPath)"

  mkdir -p "$RELEASE_PATH/bin"
  mkdir -p "$RELEASE_PATH/lib"
  rsync ./ci/build/code-server.sh "$RELEASE_PATH/bin/code-server"
  rsync "$node_path" "$RELEASE_PATH/lib/node"

  chmod 755 "$RELEASE_PATH/lib/node"

  pushd "$RELEASE_PATH"
  npm install --unsafe-perm --omit=dev
  # Code deletes some files from the extension node_modules directory which
  # leaves broken symlinks in the corresponding .bin directory.  nfpm will fail
  # on these broken symlinks so clean them up.
  rm -fr "./lib/vscode/extensions/node_modules/.bin"
  popd
}

main "$@"


================================================
FILE: ci/build/build-vscode.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

# Builds vscode into lib/vscode/out-vscode.

# MINIFY controls whether a minified version of vscode is built.
MINIFY=${MINIFY-true}

delete-bin-script() {
  rm -f "lib/vscode-reh-web-linux-x64/bin/$1"
}

copy-bin-script() {
  local script="$1"
  local dest="lib/vscode-reh-web-linux-x64/bin/$script"
  cp "lib/vscode/resources/server/bin/$script" "$dest"
  sed -i.bak "s/@@VERSION@@/$(vscode_version)/g" "$dest"
  sed -i.bak "s/@@COMMIT@@/$BUILD_SOURCEVERSION/g" "$dest"
  sed -i.bak "s/@@APPNAME@@/code-server/g" "$dest"

  # Fix Node path on Darwin and Linux.
  # We do not want expansion here; this text should make it to the file as-is.
  # shellcheck disable=SC2016
  sed -i.bak 's/^ROOT=\(.*\)$/VSROOT=\1\nROOT="$(dirname "$(dirname "$VSROOT")")"/g' "$dest"
  sed -i.bak 's/ROOT\/out/VSROOT\/out/g' "$dest"
  # We do not want expansion here; this text should make it to the file as-is.
  # shellcheck disable=SC2016
  sed -i.bak 's/$ROOT\/node/${NODE_EXEC_PATH:-$ROOT\/lib\/node}/g' "$dest"

  # Fix Node path on Windows.
  sed -i.bak 's/^set ROOT_DIR=\(.*\)$/set ROOT_DIR=%~dp0..\\..\\..\\..\r\nset VSROOT_DIR=\1/g' "$dest"
  sed -i.bak 's/%ROOT_DIR%\\out/%VSROOT_DIR%\\out/g' "$dest"

  chmod +x "$dest"
  rm "$dest.bak"
}

main() {
  cd "$(dirname "${0}")/../.."

  source ./ci/lib.sh

  # Set the commit Code will embed into the product.json.  We need to do this
  # since Code tries to get the commit from the `.git` directory which will fail
  # as it is a submodule.
  #
  # Also, we use code-server's commit rather than VS Code's otherwise it would
  # not update when only our patch files change, and that will cause caching
  # issues where the browser keeps using outdated code.
  export BUILD_SOURCEVERSION
  BUILD_SOURCEVERSION=$(git rev-parse HEAD)

  pushd lib/vscode

  if [[ ! ${VERSION-} ]]; then
    echo "VERSION not set. Please set before running this script:"
    echo "VERSION='0.0.0' npm run build:vscode"
    exit 1
  fi

  # Add the date, our name, links, enable telemetry (this just makes telemetry
  # available; telemetry can still be disabled by flag or setting), and
  # configure trusted extensions (since some, like github.copilot-chat, never
  # ask to be trusted and this is the only way to get auth working).
  #
  # This needs to be done before building as Code will read this file and embed
  # it into the client-side code.
  git checkout product.json             # Reset in case the script exited early.
  cp product.json product.original.json # Since jq has no inline edit.
  jq --slurp '.[0] * .[1]' product.original.json <(
    cat << EOF
  {
    "enableTelemetry": true,
    "quality": "stable",
    "codeServerVersion": "$VERSION",
    "nameShort": "code-server",
    "nameLong": "code-server",
    "applicationName": "code-server",
    "dataFolderName": ".code-server",
    "win32MutexName": "codeserver",
    "licenseUrl": "https://github.com/coder/code-server/blob/main/LICENSE",
    "win32DirName": "code-server",
    "win32NameVersion": "code-server",
    "win32AppUserModelId": "coder.code-server",
    "win32ShellNameShort": "c&ode-server",
    "darwinBundleIdentifier": "com.coder.code.server",
    "linuxIconName": "com.coder.code.server",
    "reportIssueUrl": "https://github.com/coder/code-server/issues/new",
    "documentationUrl": "https://go.microsoft.com/fwlink/?LinkID=533484#vscode",
    "keyboardShortcutsUrlMac": "https://go.microsoft.com/fwlink/?linkid=832143",
    "keyboardShortcutsUrlLinux": "https://go.microsoft.com/fwlink/?linkid=832144",
    "keyboardShortcutsUrlWin": "https://go.microsoft.com/fwlink/?linkid=832145",
    "introductoryVideosUrl": "https://go.microsoft.com/fwlink/?linkid=832146",
    "tipsAndTricksUrl": "https://go.microsoft.com/fwlink/?linkid=852118",
    "newsletterSignupUrl": "https://www.research.net/r/vsc-newsletter",
    "linkProtectionTrustedDomains": [
      "https://open-vsx.org"
    ],
    "trustedExtensionAuthAccess": [
      "vscode.git", "vscode.github",
      "github.vscode-pull-request-github",
      "github.copilot", "github.copilot-chat"
    ],
    "aiConfig": {
      "ariaKey": "code-server"
    }
  }
EOF
  ) > product.json

  # Any platform here works since we will do our own packaging.  We have to do
  # this because we have an NPM package that could be installed on any platform.
  # The correct platform dependencies and scripts will be installed as part of
  # the post-install during `npm install` or when building a standalone release.
  node --max-old-space-size=16384 --optimize-for-size \
       ./node_modules/gulp/bin/gulp.js \
       "vscode-reh-web-linux-x64${MINIFY:+-min}"

  # Reset so if you develop after building you will not be stuck with the wrong
  # commit (the dev client will use `oss-dev` but the dev server will still use
  # product.json which will have `stable-$commit`).
  git checkout product.json

  popd

  pushd lib/vscode-reh-web-linux-x64
  # Make sure Code took the version we set in the environment variable.  Not
  # having a version will break display languages.
  if ! jq -e .commit product.json; then
    echo "'commit' is missing from product.json"
    exit 1
  fi
  popd

  # These provide a `code-server` command in the integrated terminal to open
  # files in the current instance.
  delete-bin-script remote-cli/code-server
  copy-bin-script remote-cli/code-darwin.sh
  copy-bin-script remote-cli/code-linux.sh
  copy-bin-script remote-cli/code.cmd

  # These provide a way for terminal applications to open browser windows.
  delete-bin-script helpers/browser.sh
  copy-bin-script helpers/browser-darwin.sh
  copy-bin-script helpers/browser-linux.sh
  copy-bin-script helpers/browser.cmd
}

main "$@"


================================================
FILE: ci/build/clean.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

main() {
  cd "$(dirname "${0}")/../.."
  source ./ci/lib.sh

  git clean -Xffd
}

main "$@"


================================================
FILE: ci/build/code-server-nfpm.sh
================================================
#!/usr/bin/env sh

exec /usr/lib/code-server/bin/code-server "$@"


================================================
FILE: ci/build/code-server-user.service
================================================
[Unit]
Description=code-server
After=network.target

[Service]
Type=exec
ExecStart=/usr/bin/code-server
Restart=always

[Install]
WantedBy=default.target


================================================
FILE: ci/build/code-server.sh
================================================
#!/bin/sh
set -eu

# This script is intended to be bundled into the standalone releases.
# Runs code-server with the bundled node binary.

_realpath() {
  # See https://github.com/coder/code-server/issues/1537 on why no realpath or readlink -f.

  script="$1"
  cd "$(dirname "$script")"

  while [ -L "$(basename "$script")" ]; do
    script="$(readlink "$(basename "$script")")"
    cd "$(dirname "$script")"
  done

  echo "$PWD/$(basename "$script")"
}

root() {
  script="$(_realpath "$0")"
  bin_dir="$(dirname "$script")"
  dirname "$bin_dir"
}

ROOT="$(root)"
exec "$ROOT/lib/node" "$ROOT" "$@"


================================================
FILE: ci/build/code-server@.service
================================================
[Unit]
Description=code-server
After=network.target

[Service]
Type=exec
ExecStart=/usr/bin/code-server
Restart=always
User=%i

[Install]
WantedBy=default.target


================================================
FILE: ci/build/nfpm.yaml
================================================
name: "code-server"
arch: "${NFPM_ARCH}"
platform: "linux"
version: "v${VERSION}"
section: "devel"
priority: "optional"
maintainer: "Joe Previte <joe@coder.com>"
description: |
  Run VS Code in the browser.
vendor: "Coder"
homepage: "https://github.com/coder/code-server"
license: "MIT"

contents:
  - src: ./ci/build/code-server-nfpm.sh
    dst: /usr/bin/code-server

  - src: ./ci/build/code-server@.service
    dst: /usr/lib/systemd/system/code-server@.service

  - src: ./ci/build/code-server-user.service
    dst: /usr/lib/systemd/user/code-server.service

  - src: ./release-standalone/*
    dst: /usr/lib/code-server


================================================
FILE: ci/build/npm-postinstall.sh
================================================
#!/usr/bin/env sh
set -eu

# Copied from ../lib.sh except we do not rename Darwin and we do not need to
# detect Alpine.
os() {
  osname=$(uname | tr '[:upper:]' '[:lower:]')
  case $osname in
    cygwin* | mingw*) osname="windows" ;;
  esac
  echo "$osname"
}

# Create a symlink at $2 pointing to $1 on any platform.  Anything that
# currently exists at $2 will be deleted.
symlink() {
  source="$1"
  dest="$2"
  rm -rf "$dest"
  case $OS in
    windows) mklink /J "$dest" "$source" ;;
    *) ln -s "$source" "$dest" ;;
  esac
}

# VS Code bundles some modules into an asar which is an archive format that
# works like tar. It then seems to get unpacked into node_modules.asar.
#
# I don't know why they do this but all the dependencies they bundle already
# exist in node_modules so just symlink it. We have to do this since not only
# Code itself but also extensions will look specifically in this directory for
# files (like the ripgrep binary or the oniguruma wasm).
symlink_asar() {
  symlink node_modules node_modules.asar
}

# Make a symlink at bin/$1/$3 pointing to the platform-specific version of the
# script in $2.  The extension of the link will be .cmd for Windows otherwise it
# will be whatever is in $4 (or no extension if $4 is not set).
symlink_bin_script() {
  oldpwd="$(pwd)"
  cd "bin/$1"
  source="$2"
  dest="$3"
  ext="${4-}"
  case $OS in
    windows) symlink "$source.cmd" "$dest.cmd" ;;
    darwin | macos) symlink "$source-darwin.sh" "$dest$ext" ;;
    *) symlink "$source-linux.sh" "$dest$ext" ;;
  esac
  cd "$oldpwd"
}

command_exists() {
  if [ ! "$1" ]; then return 1; fi
  command -v "$@" > /dev/null
}

is_root() {
  if command_exists id && [ "$(id -u)" = 0 ]; then
    return 0
  fi
  return 1
}

OS="$(os)"

main() {
  # Grabs the major version of node from $npm_config_user_agent which looks like
  # yarn/1.21.1 npm/? node/v14.2.0 darwin x64
  major_node_version=$(echo "$npm_config_user_agent" | sed -n 's/.*node\/v\([^.]*\).*/\1/p')

  if [ -n "${FORCE_NODE_VERSION:-}" ]; then
    echo "WARNING: Overriding required Node.js version to v$FORCE_NODE_VERSION"
    echo "This could lead to broken functionality, and is unsupported."
    echo "USE AT YOUR OWN RISK!"
  fi

  if [ "$major_node_version" -ne "${FORCE_NODE_VERSION:-22}" ]; then
    echo "ERROR: code-server currently requires node v22."
    if [ -n "$FORCE_NODE_VERSION" ]; then
      echo "However, you have overrided the version check to use v$FORCE_NODE_VERSION."
    fi
    echo "We have detected that you are on node v$major_node_version"
    echo "You can override this version check by setting \$FORCE_NODE_VERSION,"
    echo "but configurations that do not use the same node version are unsupported."
    exit 1
  fi

  # Under npm, if we are running as root, we need --unsafe-perm otherwise
  # post-install scripts will not have sufficient permissions to do their thing.
  if is_root; then
    case "${npm_config_user_agent-}" in npm*)
      if [ "${npm_config_unsafe_perm-}" != "true" ]; then
        echo "Please pass --unsafe-perm to npm to install code-server"
        echo "Otherwise post-install scripts will not have permissions to run"
        echo "See https://docs.npmjs.com/misc/config#unsafe-perm"
        echo "See https://stackoverflow.com/questions/49084929/npm-sudo-global-installation-unsafe-perm"
        exit 1
      fi
      ;;
    esac
  fi

  if ! vscode_install; then
    echo "You may not have the required dependencies to build the native modules."
    echo "Please see https://github.com/coder/code-server/blob/main/docs/npm.md"
    exit 1
  fi

  if [ -n "${FORCE_NODE_VERSION:-}" ]; then
    echo "WARNING: The required Node.js version was overriden to v$FORCE_NODE_VERSION"
    echo "This could lead to broken functionality, and is unsupported."
    echo "USE AT YOUR OWN RISK!"
  fi
}

install_with_yarn_or_npm() {
  echo "User agent: ${npm_config_user_agent-none}"
  # For development we enforce npm, but for installing the package as an
  # end-user we want to keep using whatever package manager is in use.
  case "${npm_config_user_agent-}" in
    npm*)
      if ! npm install --unsafe-perm --omit=dev; then
        return 1
      fi
      ;;
    yarn*)
      if ! yarn --production --frozen-lockfile --no-default-rc; then
        return 1
      fi
      ;;
    *)
      echo "Could not determine which package manager is being used to install code-server"
      exit 1
      ;;
  esac
  return 0
}

vscode_install() {
  echo 'Installing Code dependencies...'
  cd lib/vscode
  if ! install_with_yarn_or_npm; then
    return 1
  fi

  symlink_asar
  symlink_bin_script remote-cli code code-server
  symlink_bin_script helpers browser browser .sh

  cd extensions
  if ! install_with_yarn_or_npm; then
    return 1
  fi

  return 0
}

main "$@"


================================================
FILE: ci/dev/doctoc.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

main() {
  cd "$(dirname "$0")/../.."

  doctoc --title '# FAQ' docs/FAQ.md > /dev/null
  doctoc --title '# Setup Guide' docs/guide.md > /dev/null
  doctoc --title '# Install' docs/install.md > /dev/null
  doctoc --title '# npm Install Requirements' docs/npm.md > /dev/null
  doctoc --title '# Contributing' docs/CONTRIBUTING.md > /dev/null
  doctoc --title '# Maintaining' docs/MAINTAINING.md > /dev/null
  doctoc --title '# Contributor Covenant Code of Conduct' docs/CODE_OF_CONDUCT.md > /dev/null
  doctoc --title '# iPad' docs/ipad.md > /dev/null
  doctoc --title '# Termux' docs/termux.md > /dev/null

  if [[ ${CI-} && $(git ls-files --other --modified --exclude-standard) ]]; then
    echo "Files need generation or are formatted incorrectly:"
    git -c color.ui=always status | grep --color=no '\[31m'
    echo "Please run the following locally:"
    echo "  npm run doctoc"
    exit 1
  fi
}

main "$@"


================================================
FILE: ci/dev/gen_icons.sh
================================================
#!/bin/sh
set -eu

# Generate icons from a single favicon.svg.  favicon.svg should have no fill
# colors set.
main() {
  cd src/browser/media

  # We need .ico for backwards compatibility.  The other two are the only icon
  # sizes required by Chrome and we use them for stuff like apple-touch-icon as
  # well.  https://web.dev/add-manifest/
  #
  # This should be enough and we can always add more if there are problems.
  #
  # -quiet to avoid https://github.com/ImageMagick/ImageMagick/issues/884
  # -background defaults to white but we want it transparent.
  # -density somehow makes the image both sharper and smaller in file size.
  #
  # https://imagemagick.org/script/command-line-options.php#background
  convert -quiet -background transparent \
          -resize 256x256 -density 256x256 \
          favicon.svg favicon.ico

  # Generate PWA icons.  There should be enough padding to support masking.
  convert -quiet -border 60x60 -bordercolor white -background white \
          -resize 192x192 -density 192x192 \
          favicon.svg pwa-icon-maskable-192.png
  convert -quiet -border 160x160 -bordercolor white -background white \
          -resize 512x512 -density 512x512 \
          favicon.svg pwa-icon-maskable-512.png

  # Generate non-maskable PWA icons.
  magick pwa-icon-maskable-192.png \
         \( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 50,50" \) \
         -channel-fx "| gray=>alpha" \
         pwa-icon-192.png
  magick pwa-icon-maskable-512.png \
         \( +clone -threshold 101% -fill white -draw "roundRectangle 0,0 %[fx:int(w)],%[fx:int(h)] 100,100" \) \
         -channel-fx "| gray=>alpha" \
         pwa-icon-512.png

  # The following adds dark mode support for the favicon as
  # favicon-dark-support.svg There is no similar capability for pwas or .ico so
  # we can only add support to the svg.
  favicon_dark_style="<style>@media (prefers-color-scheme: dark) {* { fill: white; }}</style>"
  cp favicon.svg favicon-dark-support.svg
  sed "s%<path%$favicon_dark_style\n  <path%" favicon.svg > favicon-dark-support.svg
}

main "$@"


================================================
FILE: ci/dev/lint-scripts.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

main() {
  cd "$(dirname "$0")/../.."
  shellcheck -e SC2046,SC2164,SC2154,SC1091,SC1090,SC2002 $(git ls-files '*.sh' | grep -v 'lib/vscode')
}

main "$@"


================================================
FILE: ci/dev/postinstall.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

# Install dependencies in $1.
install-deps() {
  local args=()
  if [[ ${CI-} ]]; then
    args+=(ci)
  else
    args+=(install)
  fi
  # If there is no package.json then npm will look upward and end up installing
  # from the root resulting in an infinite loop (this can happen if you have not
  # checked out the submodule yet for example).
  if [[ ! -f "$1/package.json" ]]; then
    echo "$1/package.json is missing; did you run git submodule update --init?"
    exit 1
  fi
  pushd "$1"
  echo "Installing dependencies for $PWD"
  npm "${args[@]}"
  popd
}

main() {
  cd "$(dirname "$0")/../.."
  source ./ci/lib.sh

  install-deps test
  install-deps test/e2e/extensions/test-extension
  # We don't need these when running the integration tests
  # so you can pass SKIP_SUBMODULE_DEPS
  if [[ ! ${SKIP_SUBMODULE_DEPS-} ]]; then
    install-deps lib/vscode
  fi
}

main "$@"


================================================
FILE: ci/dev/preinstall.js
================================================
if (process.env.npm_execpath.includes("yarn")) {
  throw new Error("`yarn` is no longer supported; please use `npm install` instead")
}


================================================
FILE: ci/dev/test-e2e.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

help() {
  echo >&2 "  You can build with 'npm run watch' or you can build a release"
  echo >&2 "  For example: 'npm run build && npm run build:vscode && KEEP_MODULES=1 npm run release'"
  echo >&2 "  Then 'CODE_SERVER_TEST_ENTRY=./release npm run test:e2e'"
  echo >&2 "  You can manually run that release with 'node ./release'"
}

main() {
  cd "$(dirname "$0")/../.."

  source ./ci/lib.sh

  pushd test/e2e/extensions/test-extension
  echo "Building test extension"
  npm run build
  popd

  local dir="$PWD"
  if [[ ! ${CODE_SERVER_TEST_ENTRY-} ]]; then
    echo "Set CODE_SERVER_TEST_ENTRY to test another build of code-server"
  else
    pushd "$CODE_SERVER_TEST_ENTRY"
    dir="$PWD"
    popd
  fi

  echo "Testing build in '$dir'"

  # Simple sanity checks to see that we've built. There could still be things
  # wrong (native modules version issues, incomplete build, etc).
  if [[ ! -d $dir/out ]]; then
    echo >&2 "No code-server build detected"
    help
    exit 1
  fi

  if [[ ! -d $dir/lib/vscode/out ]]; then
    echo >&2 "No VS Code build detected"
    help
    exit 1
  fi

  cd test
  ./node_modules/.bin/playwright test "$@"
}

main "$@"


================================================
FILE: ci/dev/test-integration.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

help() {
  echo >&2 "  You can build the standalone release with 'npm run release:standalone'"
  echo >&2 "  Or you can pass in a custom path."
  echo >&2 "  CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' npm run test:integration"
}

# Make sure a code-server release works. You can pass in the path otherwise it
# will look for release-standalone in the current directory.
#
# This is to make sure we don't have Node version errors or any other
# compilation-related errors.
main() {
  cd "$(dirname "$0")/../.."

  source ./ci/lib.sh

  local path="$RELEASE_PATH-standalone/bin/code-server"
  if [[ ! ${CODE_SERVER_PATH-} ]]; then
    echo "Set CODE_SERVER_PATH to test another build of code-server"
  else
    path="$CODE_SERVER_PATH"
  fi

  echo "Running tests with code-server binary: '$path'"

  if [[ ! -f $path ]]; then
    echo >&2 "No code-server build detected"
    echo >&2 "Looked in $path"
    help
    exit 1
  fi

  CODE_SERVER_PATH="$path" ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration" --testPathIgnorePatterns "./test/integration/fixtures"
}

main "$@"


================================================
FILE: ci/dev/test-native.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

help() {
  echo >&2 "  You can build the standalone release with 'npm run release:standalone'"
  echo >&2 "  Or you can pass in a custom path."
  echo >&2 "  CODE_SERVER_PATH='/var/tmp/coder/code-server/bin/code-server' npm run test:integration"
}

# Make sure a code-server release works. You can pass in the path otherwise it
# will look for release-standalone in the current directory.
#
# This is to make sure we don't have Node version errors or any other
# compilation-related errors.
main() {
  cd "$(dirname "$0")/../.."

  source ./ci/lib.sh

  local path="$RELEASE_PATH-standalone/bin/code-server"
  if [[ ! ${CODE_SERVER_PATH-} ]]; then
    echo "Set CODE_SERVER_PATH to test another build of code-server"
  else
    path="$CODE_SERVER_PATH"
  fi

  echo "Running tests with code-server binary: '$path'"

  if [[ ! -f $path ]]; then
    echo >&2 "No code-server build detected"
    echo >&2 "Looked in $path"
    help
    exit 1
  fi

  CODE_SERVER_PATH="$path" ./test/node_modules/.bin/jest "$@" --coverage=false --testRegex "./test/integration/help.test.ts"
}

main "$@"


================================================
FILE: ci/dev/test-scripts.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

main() {
  cd "$(dirname "$0")/../.."
  bats ./test/scripts
}

main "$@"


================================================
FILE: ci/dev/test-unit.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

main() {
  cd "$(dirname "$0")/../.."

  source ./ci/lib.sh

  # We must keep jest in a sub-directory. See ../../test/package.json for more
  # information. We must also run it from the root otherwise coverage will not
  # include our source files.
  ./test/node_modules/.bin/jest "$@" --testRegex "./test/unit/.*ts"
}

main "$@"


================================================
FILE: ci/dev/watch.ts
================================================
import { spawn, ChildProcess } from "child_process"
import * as path from "path"
import { onLine, OnLineCallback } from "../../src/node/util"

interface DevelopmentCompilers {
  [key: string]: ChildProcess | undefined
  vscode: ChildProcess
  vscodeWebExtensions: ChildProcess
  codeServer: ChildProcess
  plugins: ChildProcess | undefined
}

class Watcher {
  private rootPath = path.resolve(process.cwd())
  private readonly paths = {
    /** Path to uncompiled VS Code source. */
    vscodeDir: path.join(this.rootPath, "lib/vscode"),
    pluginDir: process.env.PLUGIN_DIR,
  }

  //#region Web Server

  /** Development web server. */
  private webServer: ChildProcess | undefined

  private reloadWebServer = (): void => {
    if (this.webServer) {
      this.webServer.kill()
    }

    // Pass CLI args, save for `node` and the initial script name.
    const args = process.argv.slice(2)
    this.webServer = spawn("node", [path.join(this.rootPath, "out/node/entry.js"), ...args])
    onLine(this.webServer, (line) => console.log("[code-server]", line))
    const { pid } = this.webServer

    this.webServer.on("exit", () => console.log("[code-server]", `Web process ${pid} exited`))

    console.log("\n[code-server]", `Spawned web server process ${pid}`)
  }

  //#endregion

  //#region Compilers

  private readonly compilers: DevelopmentCompilers = {
    codeServer: spawn("tsc", ["--watch", "--pretty", "--preserveWatchOutput"], { cwd: this.rootPath }),
    vscode: spawn("npm", ["run", "watch"], { cwd: this.paths.vscodeDir }),
    vscodeWebExtensions: spawn("npm", ["run", "watch-web"], { cwd: this.paths.vscodeDir }),
    plugins: this.paths.pluginDir
      ? spawn("npm", ["run", "build", "--watch"], { cwd: this.paths.pluginDir })
      : undefined,
  }

  public async initialize(): Promise<void> {
    for (const event of ["SIGINT", "SIGTERM"]) {
      process.on(event, () => this.dispose(0))
    }

    for (const [processName, devProcess] of Object.entries(this.compilers)) {
      if (!devProcess) continue

      devProcess.on("exit", (code) => {
        console.log(`[${processName}]`, "Terminated unexpectedly")
        this.dispose(code)
      })

      if (devProcess.stderr) {
        devProcess.stderr.on("data", (d: string | Uint8Array) => process.stderr.write(d))
      }
    }

    onLine(this.compilers.vscode, this.parseVSCodeLine)
    onLine(this.compilers.codeServer, this.parseCodeServerLine)

    if (this.compilers.plugins) {
      onLine(this.compilers.plugins, this.parsePluginLine)
    }
  }

  //#endregion

  //#region Line Parsers

  private parseVSCodeLine: OnLineCallback = (strippedLine, originalLine) => {
    if (!strippedLine.length) return

    console.log("[Code OSS]", originalLine)

    if (strippedLine.includes("Finished compilation with")) {
      console.log("[Code OSS] ✨ Finished compiling! ✨", "(Refresh your web browser ♻️)")
      this.reloadWebServer()
    }
  }

  private parseCodeServerLine: OnLineCallback = (strippedLine, originalLine) => {
    if (!strippedLine.length) return

    console.log("[Compiler][code-server]", originalLine)

    if (strippedLine.includes("Watching for file changes")) {
      console.log("[Compiler][code-server]", "Finished compiling!", "(Refresh your web browser ♻️)")
      this.reloadWebServer()
    }
  }

  private parsePluginLine: OnLineCallback = (strippedLine, originalLine) => {
    if (!strippedLine.length) return

    console.log("[Compiler][Plugin]", originalLine)

    if (strippedLine.includes("Watching for file changes...")) {
      this.reloadWebServer()
    }
  }

  //#endregion

  //#region Utilities

  private dispose(code: number | null): void {
    for (const [processName, devProcess] of Object.entries(this.compilers)) {
      console.log(`[${processName}]`, "Killing...\n")
      devProcess?.removeAllListeners()
      devProcess?.kill()
    }
    process.exit(typeof code === "number" ? code : 0)
  }

  //#endregion
}

async function main(): Promise<void> {
  try {
    const watcher = new Watcher()
    await watcher.initialize()
  } catch (error: any) {
    console.error(error.message)
    process.exit(1)
  }
}

main()


================================================
FILE: ci/helm-chart/.helmignore
================================================
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/


================================================
FILE: ci/helm-chart/Chart.yaml
================================================
apiVersion: v2
name: code-server
description: A Helm chart for coder/code-server

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 3.33.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 4.109.5


================================================
FILE: ci/helm-chart/templates/NOTES.txt
================================================
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
  {{- range .paths }}
  http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}
  {{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
  export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "code-server.fullname" . }})
  export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
  echo http://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
     NOTE: It may take a few minutes for the LoadBalancer IP to be available.
           You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "code-server.fullname" . }}'
  export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "code-server.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
  echo http://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl port-forward --namespace {{ .Release.Namespace }} service/{{ include "code-server.fullname" . }} 8080:http
{{- end }}

Administrator credentials:

  Password: echo $(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "code-server.fullname" . }} -o jsonpath="{.data.password}" | base64 --decode)


================================================
FILE: ci/helm-chart/templates/_helpers.tpl
================================================
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "code-server.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "code-server.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "code-server.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
{{- end -}}

{{/*
Common labels
*/}}
{{- define "code-server.labels" -}}
helm.sh/chart: {{ include "code-server.chart" . }}
{{ include "code-server.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "code-server.selectorLabels" -}}
app.kubernetes.io/name: {{ include "code-server.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "code-server.serviceAccountName" -}}
{{- if .Values.serviceAccount.create -}}
    {{ default (include "code-server.fullname" .) .Values.serviceAccount.name }}
{{- else -}}
    {{ default "default" .Values.serviceAccount.name }}
{{- end -}}
{{- end -}}


================================================
FILE: ci/helm-chart/templates/deployment.yaml
================================================
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "code-server.fullname" . }}
  labels:
    {{- include "code-server.labels" . | nindent 4 }}
  {{- if .Values.annotations }}
  annotations: {{- toYaml .Values.annotations | nindent 4 }}
  {{- end }}
spec:
  replicas: {{ .Values.replicaCount | default 1 }}
  strategy:
    type: Recreate
  selector:
    matchLabels:
      {{- include "code-server.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "code-server.selectorLabels" . | nindent 8 }}
      {{- if .Values.podAnnotations }}
      annotations: {{- toYaml .Values.podAnnotations | nindent 8 }}
      {{- end }}
    spec:
      imagePullSecrets: {{- toYaml .Values.imagePullSecrets | nindent 8 }}
      {{- if .Values.hostnameOverride }}
      hostname: {{ .Values.hostnameOverride }}
      {{- end }}
      {{- if .Values.priorityClassName }}
      priorityClassName: {{ .Values.priorityClassName }}
      {{- end }}
      {{- if .Values.securityContext.enabled }}
      securityContext:
        fsGroup: {{ .Values.securityContext.fsGroup }}
      {{- end }}
      {{- if or (and .Values.volumePermissions.enabled .Values.persistence.enabled) .Values.extraInitContainers }}
      initContainers:
      {{- if and .Values.volumePermissions.enabled .Values.persistence.enabled }}
      - name: init-chmod-data
        image: busybox:latest
        imagePullPolicy: IfNotPresent
        command:
          - sh
          - -c
          - |
            chown -R {{ .Values.securityContext.runAsUser }}:{{ .Values.securityContext.fsGroup }} /home/coder
        securityContext:
          runAsUser: {{ .Values.volumePermissions.securityContext.runAsUser }}
        volumeMounts:
        - name: data
          mountPath: /home/coder
      {{- end }}
{{- if .Values.extraInitContainers }}
{{ tpl .Values.extraInitContainers . | indent 6}}
{{- end }}
      {{- end }}
      containers:
{{- if .Values.extraContainers }}
{{ tpl .Values.extraContainers . | indent 8}}
{{- end }}
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          {{- if .Values.securityContext.enabled }}
          securityContext:
            runAsUser: {{ .Values.securityContext.runAsUser }}
          {{- end }}
          {{- if .Values.lifecycle.enabled }}
          lifecycle:
            {{- if .Values.lifecycle.postStart }}
            postStart:
              {{ toYaml .Values.lifecycle.postStart | nindent 14 }}
            {{- end }}
            {{- if .Values.lifecycle.preStop }}
            preStop:
              {{ toYaml .Values.lifecycle.preStop | nindent 14 }}
            {{- end }}
          {{- end }}
          env:
        {{- if .Values.extraVars }}
{{ toYaml .Values.extraVars | indent 10 }}
        {{- end }}
          - name: PASSWORD
            valueFrom:
              secretKeyRef:
              {{- if .Values.existingSecret }}
                name: {{ .Values.existingSecret }}
              {{- else }}
                name: {{ template "code-server.fullname" . }}
              {{- end }}
                key: password
        {{- if .Values.extraArgs }}
          args:
{{ toYaml .Values.extraArgs | indent 10 }}
        {{- end }}
          volumeMounts:
          - name: data
            mountPath: /home/coder
          {{- range .Values.extraConfigmapMounts }}
          - name: {{ .name }}
            mountPath: {{ .mountPath }}
            subPath: {{ .subPath | default "" }}
            readOnly: {{ .readOnly }}
          {{- end }}
          {{- range .Values.extraSecretMounts }}
          - name: {{ .name }}
            mountPath: {{ .mountPath }}
            subPath: {{ .subPath | default "" }}
            readOnly: {{ .readOnly }}
          {{- end }}
          {{- range .Values.extraVolumeMounts }}
          - name: {{ .name }}
            mountPath: {{ .mountPath }}
            subPath: {{ .subPath | default "" }}
            readOnly: {{ .readOnly }}
          {{- end }}
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          {{- range .Values.extraPorts }}
            - name: {{ .name }}
              containerPort: {{ .port }}
              protocol: {{ .protocol }}
          {{- end }}
          {{- if ne .Values.livenessProbe.enabled false }}
          livenessProbe:
            httpGet:
              path: /healthz
              port: http
          {{- end }}
          {{- if ne .Values.readinessProbe.enabled false }}
          readinessProbe:
            httpGet:
              path: /healthz
              port: http
          {{- end }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
    {{- with .Values.affinity }}
      affinity:
        {{- tpl . $ | nindent 8 }}
    {{- end }}
    {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
    {{- end }}
      serviceAccountName: {{ template "code-server.serviceAccountName" . }}
      volumes:
      - name: data
      {{- if .Values.persistence.enabled }}
        {{- if not .Values.persistence.hostPath }}
        persistentVolumeClaim:
          claimName: {{ .Values.persistence.existingClaim | default (include "code-server.fullname" .) }}
        {{- else }}
        hostPath:
          path: {{ .Values.persistence.hostPath }}
          type: Directory
        {{- end -}}
      {{- else }}
        emptyDir: {}
      {{- end -}}
      {{- range .Values.extraSecretMounts }}
      - name: {{ .name }}
        secret:
          secretName: {{ .secretName }}
          defaultMode: {{ .defaultMode }}
      {{- end }}
      {{- range .Values.extraConfigmapMounts }}
      - name: {{ .name }}
        configMap:
          name: {{ .configMap }}
          defaultMode: {{ .defaultMode }}
      {{- end }}
      {{- range .Values.extraVolumeMounts }}
      - name: {{ .name }}
        {{- if .existingClaim }}
        persistentVolumeClaim:
          claimName: {{ .existingClaim }}
        {{- else if .hostPath }}
        hostPath:
          path: {{ .hostPath }}
          type: Directory
        {{- else }}
        emptyDir:
          {{- toYaml .emptyDir | nindent 10 }}
        {{- end }}
      {{- end }}


================================================
FILE: ci/helm-chart/templates/ingress.yaml
================================================
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "code-server.fullname" . -}}
{{- $svcPort := .Values.service.port -}}
{{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
  name: {{ $fullName }}
  labels:
    {{- include "code-server.labels" . | nindent 4 }}
  {{- with .Values.ingress.annotations }}
  annotations:
    {{- toYaml . | nindent 4 }}
  {{- end }}
spec:
  {{- if .Values.ingress.ingressClassName }}
  ingressClassName: {{ .Values.ingress.ingressClassName }}
  {{- end }}
  {{- if .Values.ingress.tls }}
  tls:
    {{- range .Values.ingress.tls }}
    - hosts:
        {{- range .hosts }}
        - {{ . | quote }}
        {{- end }}
      secretName: {{ .secretName }}
    {{- end }}
  {{- end }}
  rules:
  {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion -}}
    {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths:
          {{- range .paths }}
          - path: {{ . }}
            pathType: Prefix
            backend:
              service:
                name: {{ $fullName }}
                port: 
                  number: {{ $svcPort }}
          {{- end }}
    {{- end }}
  {{- else -}}
    {{- range .Values.ingress.hosts }}
    - host: {{ .host | quote }}
      http:
        paths:
          {{- range .paths }}
          - path: {{ . }}
            backend:
              serviceName: {{ $fullName }}
              servicePort: {{ $svcPort }}
          {{- end }}
    {{- end }}
  {{- end }}
{{- end }}

================================================
FILE: ci/helm-chart/templates/pvc.yaml
================================================
{{- if and (and .Values.persistence.enabled (not .Values.persistence.existingClaim)) (not .Values.persistence.hostPath) }}
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: {{ include "code-server.fullname" . }}
  namespace: {{ .Release.Namespace }}
{{- with .Values.persistence.annotations  }}
  annotations:
{{ toYaml . | indent 4 }}
{{- end }}
  labels:
    {{- include "code-server.labels" . | nindent 4 }}
spec:
  accessModes:
    - {{ .Values.persistence.accessMode | quote }}
  resources:
    requests:
      storage: {{ .Values.persistence.size | quote }}
{{- if .Values.persistence.storageClass }}
{{- if (eq "-" .Values.persistence.storageClass) }}
  storageClassName: ""
{{- else }}
  storageClassName: "{{ .Values.persistence.storageClass }}"
{{- end }}
{{- end }}
{{- end }}


================================================
FILE: ci/helm-chart/templates/secrets.yaml
================================================
{{- if not .Values.existingSecret }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ include "code-server.fullname" . }}
  annotations:
    "helm.sh/hook": "pre-install"
  labels:
    {{- include "code-server.labels" . | nindent 4 }}
type: Opaque
data:
  {{- if .Values.password }}
  password: "{{ .Values.password | b64enc }}"
  {{- else }}
  password: "{{ randAlphaNum 24 | b64enc }}"
  {{- end }}
{{- end }}


================================================
FILE: ci/helm-chart/templates/service.yaml
================================================
apiVersion: v1
kind: Service
metadata:
  name: {{ include "code-server.fullname" . }}
  labels:
    {{- include "code-server.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  {{- range .Values.extraPorts }}
    - port: {{ .port }}
      targetPort: {{ .port }}
      protocol: {{ .protocol }}
      name: {{ .name }}
  {{- end }}
  selector:
    app.kubernetes.io/name: {{ include "code-server.name" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}


================================================
FILE: ci/helm-chart/templates/serviceaccount.yaml
================================================
{{- if or .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    {{- include "code-server.labels" . | nindent 4 }}
  name: {{ template "code-server.serviceAccountName" . }}
{{- end -}}


================================================
FILE: ci/helm-chart/templates/tests/test-connection.yaml
================================================
apiVersion: v1
kind: Pod
metadata:
  name: "{{ include "code-server.fullname" . }}-test-connection"
  labels:
    {{- include "code-server.labels" . | nindent 4 }}
  annotations:
    "helm.sh/hook": test
spec:
  containers:
    - name: wget
      image: busybox
      command: ['wget']
      args:  ['{{ include "code-server.fullname" . }}:{{ .Values.service.port }}/healthz']
  restartPolicy: Never


================================================
FILE: ci/helm-chart/values.yaml
================================================
# Default values for code-server.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: codercom/code-server
  tag: '4.109.5'
  pullPolicy: Always

# Specifies one or more secrets to be used when pulling images from a
# private container repository
# https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry
imagePullSecrets: []
#  - name: registry-creds

nameOverride: ""
fullnameOverride: ""
hostnameOverride: ""

# The existing secret to use for code-server authentication in the frontend. the password is stored in the secret under the key `password`
# existingSecret: ""

serviceAccount:
  # Specifies whether a service account should be created
  create: true
  # Annotations to add to the service account
  annotations: {}
  # The name of the service account to use.
  # If not set and create is true, a name is generated using the fullname template
  name: ""

# Specifies annotations for deployment
annotations: {}

podAnnotations: {}

podSecurityContext: {}
  # fsGroup: 2000

priorityClassName: ""

service:
  type: ClusterIP
  port: 8080

ingress:
  enabled: false
  #annotations:
  #  kubernetes.io/tls-acme: "true"
  #hosts:
  #  - host: code-server.example.loc
  #    paths:
  #      - /
  ingressClassName: ""
  #tls:
  #  - secretName: code-server
  #    hosts:
  #      - code-server.example.loc

# Optional additional arguments
extraArgs: []
  # These are the arguments normally passed to code-server; run
  # code-server --help for a list of available options.
  #
  # Each argument and parameter must have its own entry; if you use
  # --param value on the command line, then enter it here as:
  #
  # - --param
  # - value
  #
  # If you receive an error like "Unknown option --param value", it may be
  # because both the parameter and value are specified as a single argument,
  # rather than two separate arguments (e.g. "- --param value" on a line).

# Optional additional environment variables
extraVars: []
#  - name: DISABLE_TELEMETRY
#    value: "true"
# if dind is desired:
#  - name: DOCKER_HOST
#    value: "tcp://localhost:2376"

##
## Init containers parameters:
## volumePermissions: Change the owner of the persist volume mountpoint to RunAsUser:fsGroup
##
volumePermissions:
  enabled: true
  securityContext:
    runAsUser: 0

## Pod Security Context
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
##
securityContext:
  enabled: true
  fsGroup: 1000
  runAsUser: 1000

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #   cpu: 100m
  #   memory: 128Mi
  # requests:
  #  cpu: 100m
  #  memory: 1000Mi

livenessProbe:
  enabled: true

readinessProbe:
  enabled: true

nodeSelector: {}

tolerations: []

affinity: {}

## Persist data to a persistent volume
persistence:
  enabled: true
  ## code-server data Persistent Volume Storage Class
  ## If defined, storageClassName: <storageClass>
  ## If set to "-", storageClassName: "", which disables dynamic provisioning
  ## If undefined (the default) or set to null, no storageClassName spec is
  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
  ##   GKE, AWS & OpenStack)
  ##
  # storageClass: "-"
  accessMode: ReadWriteOnce
  size: 10Gi
  annotations: {}
  # existingClaim: ""
  # hostPath: /data

lifecycle:
  enabled: false
  # postStart:
  #  exec:
  #    command:
  #      - /bin/bash
  #      - -c
  #      - curl -s -L SOME_SCRIPT | bash

  # for dind, the following may be helpful
  # postStart:
  #   exec:
  #     command:
  #       - /bin/sh
  #       - -c
  #       - |
  #         sudo apt-get update \
  #           && sudo apt-get install -y docker.io

## Enable an Specify container in extraContainers.
## This is meant to allow adding code-server dependencies, like docker-dind.
extraContainers: |
# If docker-dind is used, DOCKER_HOST env is mandatory to set in "extraVars"
# - name: docker-dind
#   image: docker:28.3.2-dind
#   imagePullPolicy: IfNotPresent
#   resources:
#     requests:
#       cpu: 1
#       ephemeral-storage: "50Gi"
#       memory: 10Gi
#   securityContext:
#     privileged: true
#     procMount: Default
#   env:
#     - name: DOCKER_TLS_CERTDIR
#       value: "" # disable TLS setup
#   command:
#     - dockerd
#     - --host=unix:///var/run/docker.sock
#     - --host=tcp://0.0.0.0:2376


extraInitContainers: |
# - name: customization
#   image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
#   imagePullPolicy: IfNotPresent
#   env:
#     - name: SERVICE_URL
#       value: https://open-vsx.org/vscode/gallery
#     - name: ITEM_URL
#       value: https://open-vsx.org/vscode/item
#   command:
#     - sh
#     - -c
#     - |
#       code-server --install-extension ms-python.python
#       code-server --install-extension golang.Go
#   volumeMounts:
#     - name: data
#       mountPath: /home/coder

## Additional code-server secret mounts
extraSecretMounts: []
  # - name: secret-files
  #   mountPath: /etc/secrets
  #   subPath: private.key # (optional)
  #   secretName: code-server-secret-files
  #   readOnly: true

## Additional code-server volume mounts
extraVolumeMounts: []
  # - name: extra-volume
  #   mountPath: /mnt/volume
  #   readOnly: true
  #   existingClaim: volume-claim
  #   hostPath: ""
  #   emptyDir: {}

extraConfigmapMounts: []
  # - name: certs-configmap
  #   mountPath: /etc/code-server/ssl/
  #   subPath: certificates.crt # (optional)
  #   configMap: certs-configmap
  #   readOnly: true

extraPorts: []
  # - name: minecraft
  #   port: 25565
  #   protocol: tcp


================================================
FILE: ci/lib.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

pushd() {
  builtin pushd "$@" > /dev/null
}

popd() {
  builtin popd > /dev/null
}

vscode_version() {
  jq -r .version lib/vscode/package.json
}

os() {
  osname=$(uname | tr '[:upper:]' '[:lower:]')
  case $osname in
    linux)
      # Alpine's ldd doesn't have a version flag but if you use an invalid flag
      # (like --version) it outputs the version to stderr and exits with 1.
      # TODO: Better to check /etc/os-release; see ../install.sh.
      ldd_output=$(ldd --version 2>&1 || true)
      if echo "$ldd_output" | grep -iq musl; then
        osname="alpine"
      fi
      ;;
    darwin) osname="macos" ;;
    cygwin* | mingw*) osname="windows" ;;
  esac
  echo "$osname"
}

arch() {
  cpu="$(uname -m)"
  case "$cpu" in
    aarch64) cpu=arm64 ;;
    x86_64) cpu=amd64 ;;
  esac
  echo "$cpu"
}

rsync() {
  command rsync -a --del "$@"
}

ARCH="$(arch)"
export ARCH
OS=$(os)
export OS

# RELEASE_PATH is the destination directory for the release from the root.
# Defaults to release
RELEASE_PATH="${RELEASE_PATH-release}"


================================================
FILE: ci/release-image/Dockerfile
================================================
# syntax=docker/dockerfile:experimental

ARG BASE=debian:12
FROM scratch AS packages
COPY release-packages/code-server*.deb /tmp/

FROM $BASE

RUN apt-get update \
  && apt-get install -y \
    curl \
    dumb-init \
    git \
    git-lfs \
    htop \
    locales \
    lsb-release \
    man-db \
    nano \
    openssh-client \
    procps \
    sudo \
    vim-tiny \
    wget \
    zsh \
  && git lfs install \
  && rm -rf /var/lib/apt/lists/*

# https://wiki.debian.org/Locale#Manually
RUN sed -i "s/# en_US.UTF-8/en_US.UTF-8/" /etc/locale.gen \
  && locale-gen
ENV LANG=en_US.UTF-8

RUN if grep -q 1000 /etc/passwd; then \
    userdel -r "$(id -un 1000)"; \
  fi \
  && adduser --gecos '' --disabled-password coder \
  && echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd

RUN ARCH="$(dpkg --print-architecture)" \
  && curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
  && chown root:root /usr/local/bin/fixuid \
  && chmod 4755 /usr/local/bin/fixuid \
  && mkdir -p /etc/fixuid \
  && printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml

COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
RUN --mount=from=packages,src=/tmp,dst=/tmp/packages dpkg -i /tmp/packages/code-server*$(dpkg --print-architecture).deb

# Allow users to have scripts run on container startup to prepare workspace.
# https://github.com/coder/code-server/issues/5177
ENV ENTRYPOINTD=${HOME}/entrypoint.d

EXPOSE 8080
# This way, if someone sets $DOCKER_USER, docker-exec will still work as
# the uid will remain the same. note: only relevant if -u isn't passed to
# docker-run.
USER 1000
ENV USER=coder
WORKDIR /home/coder
ENTRYPOINT ["/usr/bin/entrypoint.sh", "--bind-addr", "0.0.0.0:8080", "."]


================================================
FILE: ci/release-image/Dockerfile.fedora
================================================
# syntax=docker/dockerfile:experimental

ARG BASE=fedora:39
FROM scratch AS packages
COPY release-packages/code-server*.rpm /tmp/

FROM $BASE

RUN dnf update -y \
    && dnf install -y \
    curl \
    git \
    git-lfs \
    htop \
    nano \
    openssh-clients \
    procps \
    wget \
    zsh \
    dumb-init \
    glibc-langpack-en \
    && rm -rf /var/cache/dnf
RUN git lfs install

ENV LANG=en_US.UTF-8
RUN echo 'LANG="en_US.UTF-8"' > /etc/locale.conf

RUN useradd -u 1000 coder && echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd

RUN ARCH="$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g')" \
  && curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
  && chown root:root /usr/local/bin/fixuid \
  && chmod 4755 /usr/local/bin/fixuid \
  && mkdir -p /etc/fixuid \
  && printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml

COPY ci/release-image/entrypoint.sh /usr/bin/entrypoint.sh
RUN --mount=from=packages,src=/tmp,dst=/tmp/packages rpm -i /tmp/packages/code-server*$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g').rpm

# Allow users to have scripts run on container startup to prepare workspace.
# https://github.com/coder/code-server/issues/5177
ENV ENTRYPOINTD=${HOME}/entrypoint.d

EXPOSE 8080
# This way, if someone sets $DOCKER_USER, docker-exec will still work as
# the uid will remain the same. note: only relevant if -u isn't passed to
# docker-run.
USER 1000
ENV USER=coder
WORKDIR /home/coder
ENTRYPOINT ["/usr/bin/entrypoint.sh", "--bind-addr", "0.0.0.0:8080", "."]


================================================
FILE: ci/release-image/Dockerfile.opensuse
================================================
# syntax=docker/dockerfile:experimental

ARG BASE=opensuse/tumbleweed
FROM scratch AS packages
COPY release-packages/code-server*.rpm /tmp/

FROM $BASE

RUN zypper dup -y \
    && zypper in -y \
    curl \
    git \
    git-lfs \
    htop \
    nano \
    openssh-clients \
    procps \
    wget \
    zsh \
    sudo \
    catatonit \
    && rm -rf /var/cache/zypp /var/cache/zypper
RUN git lfs install

ENV LANG=en_US.UTF-8
RUN echo 'LANG="en_US.UTF-8"' > /etc/locale.conf

RUN useradd -u 1000 coder && echo "coder ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers.d/nopasswd

RUN ARCH="$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g')" \
  && curl -fsSL "https://github.com/boxboat/fixuid/releases/download/v0.6.0/fixuid-0.6.0-linux-$ARCH.tar.gz" | tar -C /usr/local/bin -xzf - \
  && chown root:root /usr/local/bin/fixuid \
  && chmod 4755 /usr/local/bin/fixuid \
  && mkdir -p /etc/fixuid \
  && printf "user: coder\ngroup: coder\n" > /etc/fixuid/config.yml

COPY ci/release-image/entrypoint-catatonit.sh /usr/bin/entrypoint-catatonit.sh
RUN --mount=from=packages,src=/tmp,dst=/tmp/packages rpm -i /tmp/packages/code-server*$(uname -m | sed 's/x86_64/amd64/g' | sed 's/aarch64/arm64/g').rpm

# Allow users to have scripts run on container startup to prepare workspace.
# https://github.com/coder/code-server/issues/5177
ENV ENTRYPOINTD=${HOME}/entrypoint.d

EXPOSE 8080
# This way, if someone sets $DOCKER_USER, docker-exec will still work as
# the uid will remain the same. note: only relevant if -u isn't passed to
# docker-run.
USER 1000
ENV USER=coder
WORKDIR /home/coder
ENTRYPOINT ["/usr/bin/entrypoint-catatonit.sh", "--bind-addr", "0.0.0.0:8080", "."]


================================================
FILE: ci/release-image/docker-bake.hcl
================================================
# Use this file from the top of the repo, with `-f ci/release-image/docker-bake.hcl`

# Uses env var VERSION if set;
# normally, this is set by ci/lib.sh
variable "VERSION" {
    default = "latest"
}

variable "DOCKER_REGISTRY" {
    default = "docker.io/codercom/code-server"
}

variable "GITHUB_REGISTRY" {
    default = "ghcr.io/coder/code-server"
}

group "default" {
    targets = [
        "code-server-debian-12",
        "code-server-ubuntu-focal",
        "code-server-ubuntu-noble",
        "code-server-fedora-39",
        "code-server-opensuse-tumbleweed",
    ]
}

function "prepend_hyphen_if_not_null" {
    params = [tag]
    result = notequal("","${tag}") ? "-${tag}" : "${tag}"
}

# use empty tag (tag="") to generate default tags
function "gen_tags" {
    params = [registry, tag]
    result = notequal("","${registry}") ? [
        notequal("", "${tag}") ? "${registry}:${tag}" : "${registry}:latest",
        notequal("latest",VERSION) ? "${registry}:${VERSION}${prepend_hyphen_if_not_null(tag)}" : "",
    ] : []
}

# helper function to generate tags for docker registry and github registry.
# set (DOCKER|GITHUB)_REGISTRY="" to disable corresponding registry
function "gen_tags_for_docker_and_ghcr" {
    params = [tag]
    result = concat(
        gen_tags("${DOCKER_REGISTRY}", "${tag}"),
        gen_tags("${GITHUB_REGISTRY}", "${tag}"),
    )
}

target "code-server-debian-12" {
    dockerfile = "ci/release-image/Dockerfile"
    tags = concat(
        gen_tags_for_docker_and_ghcr(""),
        gen_tags_for_docker_and_ghcr("debian"),
        gen_tags_for_docker_and_ghcr("bookworm"),
    )
    platforms = ["linux/amd64", "linux/arm64"]
}

target "code-server-ubuntu-focal" {
    dockerfile = "ci/release-image/Dockerfile"
    tags = concat(
        gen_tags_for_docker_and_ghcr("ubuntu"),
        gen_tags_for_docker_and_ghcr("focal"),
    )
    args = {
        BASE = "ubuntu:focal"
    }
    platforms = ["linux/amd64", "linux/arm64"]
}

target "code-server-ubuntu-noble" {
    dockerfile = "ci/release-image/Dockerfile"
    tags = concat(
        gen_tags_for_docker_and_ghcr("noble"),
    )
    args = {
        BASE = "ubuntu:noble"
    }
    platforms = ["linux/amd64", "linux/arm64"]
}

target "code-server-fedora-39" {
    dockerfile = "ci/release-image/Dockerfile.fedora"
    tags = concat(
        gen_tags_for_docker_and_ghcr("fedora"),
        gen_tags_for_docker_and_ghcr("39"),
    )
    args = {
        BASE = "fedora:39"
    }
    platforms = ["linux/amd64", "linux/arm64"]
}

target "code-server-opensuse-tumbleweed" {
    dockerfile = "ci/release-image/Dockerfile.opensuse"
    tags = concat(
        gen_tags_for_docker_and_ghcr("opensuse"),
        gen_tags_for_docker_and_ghcr("tumbleweed"),
    )
    args = {
        BASE = "opensuse/tumbleweed"
    }
    platforms = ["linux/amd64", "linux/arm64"]
}


================================================
FILE: ci/release-image/entrypoint-catatonit.sh
================================================
#!/bin/sh
set -eu

# We do this first to ensure sudo works below when renaming the user.
# Otherwise the current container UID may not exist in the passwd database.
eval "$(fixuid -q)"

if [ "${DOCKER_USER-}" ]; then
  USER="$DOCKER_USER"
  if [ "$DOCKER_USER" != "$(whoami)" ]; then
    echo "$DOCKER_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/nopasswd > /dev/null
    # Unfortunately we cannot change $HOME as we cannot move any bind mounts
    # nor can we bind mount $HOME into a new home as that requires a privileged container.
    sudo usermod --login "$DOCKER_USER" coder
    sudo groupmod -n "$DOCKER_USER" coder

    sudo sed -i "/coder/d" /etc/sudoers.d/nopasswd
  fi
fi

# Allow users to have scripts run on container startup to prepare workspace.
# https://github.com/coder/code-server/issues/5177
if [ -d "${ENTRYPOINTD}" ]; then
  find "${ENTRYPOINTD}" -type f -executable -print -exec {} \;
fi

exec catatonit -- /usr/bin/code-server "$@"


================================================
FILE: ci/release-image/entrypoint.sh
================================================
#!/bin/sh
set -eu

# We do this first to ensure sudo works below when renaming the user.
# Otherwise the current container UID may not exist in the passwd database.
eval "$(fixuid -q)"

if [ "${DOCKER_USER-}" ]; then
  USER="$DOCKER_USER"
  if [ -z "$(id -u "$DOCKER_USER" 2>/dev/null)" ]; then
    echo "$DOCKER_USER ALL=(ALL) NOPASSWD:ALL" | sudo tee -a /etc/sudoers.d/nopasswd > /dev/null
    # Unfortunately we cannot change $HOME as we cannot move any bind mounts
    # nor can we bind mount $HOME into a new home as that requires a privileged container.
    sudo usermod --login "$DOCKER_USER" coder
    sudo groupmod -n "$DOCKER_USER" coder

    sudo sed -i "/coder/d" /etc/sudoers.d/nopasswd
  fi
fi

# Allow users to have scripts run on container startup to prepare workspace.
# https://github.com/coder/code-server/issues/5177
if [ -d "${ENTRYPOINTD}" ]; then
  find "${ENTRYPOINTD}" -type f -executable -print -exec {} \;
fi

exec dumb-init /usr/bin/code-server "$@"


================================================
FILE: ci/steps/brew-bump.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

main() {
  # Only sourcing this so we get access to $VERSION
  source ./ci/lib.sh
  source ./ci/steps/steps-lib.sh

  echo "Checking environment variables"

  # We need VERSION to bump the brew formula
  if ! is_env_var_set "VERSION"; then
    echo "VERSION is not set"
    exit 1
  fi

  # We need HOMEBREW_GITHUB_API_TOKEN to push up commits
  if ! is_env_var_set "HOMEBREW_GITHUB_API_TOKEN"; then
    echo "HOMEBREW_GITHUB_API_TOKEN is not set"
    exit 1
  fi

  # Find the docs for bump-formula-pr here
  # https://github.com/Homebrew/brew/blob/master/Library/Homebrew/dev-cmd/bump-formula-pr.rb#L18
  local output
  if ! output=$(brew bump-formula-pr --version="${VERSION}" code-server --no-browse --no-audit --message="PR opened by @${GITHUB_ACTOR}" 2>&1); then
    if [[ $output == *"Duplicate PRs should not be opened"* ]]; then
      echo "$VERSION is already submitted"
      exit 0
    else
      echo "$output"
      exit 1
    fi
  fi
}

main "$@"


================================================
FILE: ci/steps/docker-buildx-push.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

main() {
  cd "$(dirname "$0")/../.."
  # NOTE@jsjoeio - this script assumes VERSION exists as an
  # environment variable.

  # NOTE@jsjoeio - this script assumes that you've downloaded
  # the release-packages artifact to ./release-packages before
  # running this docker buildx step
  docker buildx bake -f ci/release-image/docker-bake.hcl --push
}

main "$@"


================================================
FILE: ci/steps/publish-npm.sh
================================================
#!/usr/bin/env bash
set -euo pipefail

main() {
  cd "$(dirname "$0")/../.."
  source ./ci/lib.sh
  source ./ci/steps/steps-lib.sh

  ## Authentication tokens
  # Needed to publish on NPM
  if ! is_env_var_set "NPM_TOKEN"; then
    echo "NPM_TOKEN is not set. Cannot publish to npm without credentials."
    exit 1
  fi

  ## Publishing Information
  # All the variables below are used to determine how we should publish
  # the npm package. We also use this information for bumping the version.
  # This is because npm won't publish your package unless it's a new version.
  # i.e. for development, we bump the version to <current version>-<pr number>-<commit sha>
  # example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
  # We use this to grab the PR_NUMBER
  if ! is_env_var_set "GITHUB_REF"; then
    echo "GITHUB_REF is not set. Are you running this locally? We rely on values provided by GitHub."
    exit 1
  fi

  # We use this when setting NPM_VERSION
  if ! is_env_var_set "GITHUB_SHA"; then
    echo "GITHUB_SHA is not set. Are you running this locally? We rely on values provided by GitHub."
    exit 1
  fi

  # We use this to determine the NPM_ENVIRONMENT
  if ! is_env_var_set "GITHUB_EVENT_NAME"; then
    echo "GITHUB_EVENT_NAME is not set. Are you running this locally? We rely on values provided by GitHub."
    exit 1
  fi

  # Check that we're using at least v7 of npm CLI
  if ! command -v jq &> /dev/null; then
    echo "Couldn't find jq"
    echo "We need this in order to modify the package.json for dev builds."
    exit 1
  fi

  # This allows us to publish to npm in CI workflows
  if [[ ${CI-} ]]; then
    echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
  fi

  ## Environment
  # This string is used to determine how we should tag the npm release.
  # Environment can be one of three choices:
  # "development" - this means we tag with the PR number, allowing
  # a developer to install this version with `npm install code-server@<pr-number>`
  # "staging" - this means we tag with `beta`, allowing
  # a developer to install this version with `npm install code-server@beta`
  # "production" - this means we tag with `latest` (default), allowing
  # a developer to install this version with `npm install code-server@latest`
  if ! is_env_var_set "NPM_ENVIRONMENT"; then
    echo "NPM_ENVIRONMENT is not set."
    echo "Determining in script based on GITHUB environment variables."

    if [[ "$GITHUB_EVENT_NAME" == 'push' && "$GITHUB_REF" == 'refs/heads/main' ]]; then
      NPM_ENVIRONMENT="staging"
    else
      NPM_ENVIRONMENT="development"
    fi

  fi

  # NOTE@jsjoeio - this script assumes we have the artifact downloaded on disk
  # That happens in CI as a step before we run this.
  # https://github.com/actions/upload-artifact/issues/38
  tar -xzf release-npm-package/package.tar.gz

  # We use this to set the name of the package in the
  # package.json
  PACKAGE_NAME="code-server"

  # NOTES:@jsjoeio
  # We only need to run npm version for "development" and "staging".
  # This is because our release:prep script automatically bumps the version
  # in the package.json and we commit it as part of the release PR.
  if [[ "$NPM_ENVIRONMENT" == "production" ]]; then
    NPM_VERSION="$VERSION"
    # This means the npm version will be published as "stable"
    # and installed when a user runs `npm install code-server`
    NPM_TAG="latest"
  else
    COMMIT_SHA="$GITHUB_SHA"

    if [[ "$NPM_ENVIRONMENT" == "staging" ]]; then
      NPM_VERSION="$VERSION-beta-$COMMIT_SHA"
      # This means the npm version will be tagged with "beta"
      # and installed when a user runs `npm install code-server@beta`
      NPM_TAG="beta"
      PACKAGE_NAME="@coder/code-server-pr"
    fi

    if [[ "$NPM_ENVIRONMENT" == "development" ]]; then
      # Source: https://github.com/actions/checkout/issues/58#issuecomment-614041550
      PR_NUMBER=$(echo "$GITHUB_REF" | awk 'BEGIN { FS = "/" } ; { print $3 }')
      NPM_VERSION="$VERSION-$PR_NUMBER-$COMMIT_SHA"
      PACKAGE_NAME="@coder/code-server-pr"
      # This means the npm version will be tagged with "<pr number>"
      # and installed when a user runs `npm install code-server@<pr number>`
      NPM_TAG="$PR_NUMBER"
    fi

    echo "- tag: $NPM_TAG"
    echo "- version: $NPM_VERSION"
    echo "- package name: $PACKAGE_NAME"
    echo "- npm environment: $NPM_ENVIRONMENT"

    # We modify the version in the package.json
    # to be the current version + the PR number + commit SHA
    # or we use current version + beta + commit SHA
    # Example: "version": "4.0.1-4769-ad7b23cfe6ffd72914e34781ef7721b129a23040"
    # Example: "version": "4.0.1-beta-ad7b23cfe6ffd72914e34781ef7721b129a23040"
    pushd release
    npm version "$NPM_VERSION"
    # Use the development package name
    # This is so we don't clutter the code-server versions on npm
    # with development versions.
    # jq can't edit in place so we must store in memory and echo
    local contents
    contents="$(jq ".name |= \"$PACKAGE_NAME\"" package.json)"
    echo "${contents}" > package.json
    popd
  fi

  # We need to make sure we haven't already published the version.
  # If we get error, continue with script because we want to publish
  # If version is valid, we check if we're publishing the same one
  local hasVersion
  if hasVersion=$(npm view "$PACKAGE_NAME@$NPM_VERSION" version 2> /dev/null) && [[ $hasVersion == "$NPM_VERSION" ]]; then
    echo "$NPM_VERSION is already published under $PACKAGE_NAME"
    return
  fi

  # Since the dev builds are scoped to @coder
  # We pass --access public to ensure npm knows it's not private.
  cd release
  npm publish --tag "$NPM_TAG" --access public
}

main "$@"


================================================
FILE: ci/steps/steps-lib.sh
================================================
#!/usr/bin/env bash

# This is a library which contains functions used inside ci/steps
#
# We separated it into it's own file so that we could easily unit test
# these functions and helpers

# Checks whether and environment variable is set.
# Source: https://stackoverflow.com/a/62210688/3015595
is_env_var_set() {
  local name="${1:-}"
  if test -n "${!name:-}"; then
    return 0
  else
    return 1
  fi
}

# Checks whether a directory exists.
directory_exists() {
  local dir="${1:-}"
  if [[ -d "${dir:-}" ]]; then
    return 0
  else
    return 1
  fi
}

# Checks whether a file exists.
file_exists() {
  local file="${1:-}"
  if test -f "${file:-}"; then
    return 0
  else
    return 1
  fi
}

# Checks whether a file is executable.
is_executable() {
  local file="${1:-}"
  if [ -f "${file}" ] && [ -r "${file}" ] && [ -x "${file}" ]; then
    return 0
  else
    return 1
  fi
}


================================================
FILE: docs/CODE_OF_CONDUCT.md
================================================
<!-- prettier-ignore-start -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
# Contributor Covenant Code of Conduct

- [Contributor Covenant Code of Conduct](#contributor-covenant-code-of-conduct)
  - [Our Pledge](#our-pledge)
  - [Our Standards](#our-standards)
  - [Our Responsibilities](#our-responsibilities)
  - [Scope](#scope)
  - [Enforcement](#enforcement)
  - [Attribution](#attribution)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->

# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment
include:

- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

- The use of sexualized language or imagery and unwelcome sexual attention or
  advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or electronic
  address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.

## Scope

This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at opensource@coder.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq


================================================
FILE: docs/CONTRIBUTING.md
================================================
<!-- prettier-ignore-start -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
# Contributing

- [Requirements](#requirements)
  - [Linux-specific requirements](#linux-specific-requirements)
- [Development workflow](#development-workflow)
  - [Version updates to Code](#version-updates-to-code)
  - [Patching Code](#patching-code)
  - [Build](#build)
    - [Creating a Standalone Release](#creating-a-standalone-release)
  - [Troubleshooting](#troubleshooting)
    - [I see "Forbidden access" when I load code-server in the browser](#i-see-forbidden-access-when-i-load-code-server-in-the-browser)
    - ["Can only have one anonymous define call per script"](#can-only-have-one-anonymous-define-call-per-script)
  - [Help](#help)
- [Test](#test)
  - [Unit tests](#unit-tests)
  - [Script tests](#script-tests)
  - [Integration tests](#integration-tests)
  - [End-to-end tests](#end-to-end-tests)
- [Structure](#structure)
  - [Modifications to Code](#modifications-to-code)
  - [Currently Known Issues](#currently-known-issues)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->

## Requirements

The prerequisites for contributing to code-server are almost the same as those
for [VS Code](https://github.com/Microsoft/vscode/wiki/How-to-Contribute#prerequisites).
Here is what is needed:

- `node` v22.x
- `git` v2.x or greater
- [`git-lfs`](https://git-lfs.github.com)
- [`npm`](https://www.npmjs.com/)
  - Used to install JS packages and run scripts
- [`nfpm`](https://nfpm.goreleaser.com/)
  - Used to build `.deb` and `.rpm` packages
- [`jq`](https://stedolan.github.io/jq/)
  - Used to build code-server releases
- [`gnupg`](https://gnupg.org/index.html)
  - All commits must be signed and verified; see GitHub's [Managing commit
    signature
    verification](https://docs.github.com/en/github/authenticating-to-github/managing-commit-signature-verification)
    or follow [this tutorial](https://joeprevite.com/verify-commits-on-github)
- `quilt`
  - Used to manage patches to Code
- `rsync` and `unzip`
  - Used for code-server releases
- `bats`
  - Used to run script unit tests

### Linux-specific requirements

If you're developing code-server on Linux, make sure you have installed or
install the following dependencies:

```shell
sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev libkrb5-dev python-is-python3
```

These are required by Code. See [their Wiki](https://github.com/microsoft/vscode/wiki/How-to-Contribute#prerequisites)
for more information.

## Development workflow

1. `git clone https://github.com/coder/code-server.git` - Clone `code-server`
2. `git submodule update --init` - Clone `vscode` submodule
3. `quilt push -a` - Apply patches to the `vscode` submodule.
4. `npm install` - Install dependencies
5. `npm run watch` - Launch code-server localhost:8080. code-server will be live
   reloaded when changes are made; the browser needs to be refreshed manually.

When pulling down changes that include modifications to the patches you will
need to apply them with `quilt`. If you pull down changes that update the
`vscode` submodule you will need to run `git submodule update --init` and
re-apply the patches.

When you make a change that affects people deploying the marketplace please
update the changelog as part of your PR.

Note that building code-server takes a very, very long time, and loading it in
the browser in development mode also takes a very, very long time.

Display language (Spanish, etc) support only works in a full build; it will not
work in development mode.

Generally we prefer that PRs be squashed into `main` but you can rebase or merge
if it is important to keep the individual commits (make sure to clean up the
commits first if you are doing this).

### Version updates to Code

1. Remove any patches with `quilt pop -a`.
2. Update the `lib/vscode` submodule to the desired upstream version branch.
   1. `cd lib/vscode && git checkout release/1.66 && cd ../..`
   2. `git add lib && git commit -m "chore: update to Code <version>"`
3. Apply the patches one at a time (`quilt push`). If the application succeeds
   but the lines changed, update the patch with `quilt refresh`. If there are
   conflicts, then force apply with `quilt push -f`, manually add back the
   rejected code, then run `quilt refresh`.
4. From the code-server **project root**, run `npm install`.
5. Check the Node.js version that's used by Electron (which is shipped with VS
   Code. If necessary, update our version of Node.js to match.

### Patching Code

1. You can go through the patch stack with `quilt push` and `quilt pop`.
2. Create a new patch (`quilt new {name}.diff`) or use an existing patch.
3. Add the file(s) you are patching (`quilt add [-P patch] {file}`). A file
   **must** be added before you make changes to it.
4. Make your changes. Patches do not need to be independent of each other but
   each patch must result in a working code-server without any broken in-between
   states otherwise they are difficult to test and modify.
5. Add your changes to the patch (`quilt refresh`)
6. Add a comment in the patch about the reason for the patch and how to
   reproduce the behavior it fixes or adds. Every patch should have an e2e test
   as well.

### Build

You can build a full production as follows:

```shell
git submodule update --init
quilt push -a
npm install
npm run build
VERSION=0.0.0 npm run build:vscode
npm run release
```

This does not keep `node_modules`. If you want them to be kept, use
`KEEP_MODULES=1 npm run release`

Run your build:

```shell
cd release
npm install --omit=dev # Skip if you used KEEP_MODULES=1
# Runs the built JavaScript with Node.
node .
```

Then, to build the release package:

```shell
npm run release:standalone
npm run test:integration
npm run package
```

> On Linux, the currently running distro will become the minimum supported
> version. In our GitHub Actions CI, we use CentOS 8 for maximum compatibility.
> If you need your builds to support older distros, run the build commands
> inside a Docker container with all the build requirements installed.

#### Creating a Standalone Release

Part of the build process involves creating standalone releases. At the time of
writing, we do this for the following platforms/architectures:

- Linux amd64 (.tar.gz, .deb, and .rpm)
- Linux arm64 (.tar.gz, .deb, and .rpm)
- Linux arm7l (.tar.gz)
- Linux armhf.deb
- Linux armhf.rpm
- macOS arm64.tar.gz

Currently, these are compiled in CI using the `npm run release:standalone`
command in the `release.yaml` workflow. We then upload them to the draft release
and distribute via GitHub Releases.

### Troubleshooting

#### I see "Forbidden access" when I load code-server in the browser

This means your patches didn't apply correctly. We have a patch to remove the
auth from vanilla Code because we use our own.

Try popping off the patches with `quilt pop -a` and reapplying with `quilt push
-a`.

#### "Can only have one anonymous define call per script"

Code might be trying to use a dev or prod HTML in the wrong context. You can try
re-running code-server and setting `VSCODE_DEV=1`.

### Help

If you get stuck or need help, you can always start a new GitHub Discussion
[here](https://github.com/coder/code-server/discussions). One of the maintainers
will respond and help you out.

## Test

There are four kinds of tests in code-server:

1. Unit tests
2. Script tests
3. Integration tests
4. End-to-end tests

### Unit tests

Our unit tests are written in TypeScript and run using
[Jest](https://jestjs.io/), the testing framework].

These live under [test/unit](../test/unit).

We use unit tests for functions and things that can be tested in isolation. The
file structure is modeled closely after `/src` so it's easy for people to know
where test files should live.

### Script tests

Our script tests are written in bash and run using [bats](https://github.com/bats-core/bats-core).

These tests live under `test/scripts`.

We use these to test anything related to our scripts (most of which live under
`ci`).

### Integration tests

These are a work in progress. We build code-server and run tests with `npm run
test:integration`, which ensures that code-server builds work on their
respective platforms.

Our integration tests look at components that rely on one another. For example,
testing the CLI requires us to build and package code-server.

### End-to-end tests

The end-to-end (e2e) tests are written in TypeScript and run using
[Playwright](https://playwright.dev/).

These live under [test/e2e](../test/e2e).

Before the e2e tests run, we run `globalSetup`, which eliminates the need to log
in before each test by preserving the authentication state.

Take a look at `codeServer.test.ts` to see how you would use it (see
`test.use`).

We also have a model where you can create helpers to use within tests. See
[models/CodeServer.ts](../test/e2e/models/CodeServer.ts) for an example.

## Structure

code-server essentially serves as an HTTP API for logging in and starting a
remote Code process.

The CLI code is in [src/node](../src/node) and the HTTP routes are implemented
in [src/node/routes](../src/node/routes).

Most of the meaty parts are in the Code portion of the codebase under
[lib/vscode](../lib/vscode), which we describe next.

### Modifications to Code

Our modifications to Code can be found in the [patches](../patches) directory.
We pull in Code as a submodule pointing to an upstream release branch.

In v1 of code-server, we had Code as a submodule and used a single massive patch
that split the codebase into a front-end and a server. The front-end consisted
of the UI code, while the server ran the extensions and exposed an API to the
front-end for file access and all UI needs.

Over time, Microsoft added support to Code to run it on the web. They had made
the front-end open source, but not the server. As such, code-server v2 (and
later) uses the Code front-end and implements the server. We did this by using a
Git subtree to fork and modify Code.

Microsoft eventually made the server open source and we were able to reduce our
changes significantly. Some time later we moved back to a submodule and patches
(managed by `quilt` this time instead of the mega-patch).

As the web portion of Code continues to mature, we'll be able to shrink and
possibly eliminate our patches. In the meantime, upgrading the Code version
requires us to ensure that our changes are still applied correctly and work as
intended. In the future, we'd like to run Code unit tests against our builds to
ensure that features work as expected.

> We have [extension docs](../ci/README.md) on the CI and build system.

If the functionality you're working on does NOT depend on code from Code, please
move it out and into code-server.

### Currently Known Issues

- Creating custom Code extensions and debugging them doesn't work
- Extension profiling and tips are currently disabled


================================================
FILE: docs/FAQ.md
================================================
<!-- prettier-ignore-start -->
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
# FAQ

- [Questions?](#questions)
- [How should I expose code-server to the internet?](#how-should-i-expose-code-server-to-the-internet)
- [Can I use code-server on the iPad?](#can-i-use-code-server-on-the-ipad)
- [How does the config file work?](#how-does-the-config-file-work)
- [How do I make my keyboard shortcuts work?](#how-do-i-make-my-keyboard-shortcuts-work)
- [Why can't code-server use Microsoft's extension marketplace?](#why-cant-code-server-use-microsofts-extension-marketplace)
- [How can I request an extension that's missing from the marketplace?](#how-can-i-request-an-extension-thats-missing-from-the-marketplace)
- [How do I install an extension?](#how-do-i-install-an-extension)
- [How do I install an extension manually?](#how-do-i-install-an-extension-manually)
- [How do I use my own extensions marketplace?](#how-do-i-use-my-own-extensions-marketplace)
- [Where are extensions stored?](#where-are-extensions-stored)
- [Where is VS Code configuration stored?](#where-is-vs-code-configuration-stored)
- [How can I reuse my VS Code configuration?](#how-can-i-reuse-my-vs-code-configuration)
- [How does code-server decide what workspace or folder to open?](#how-does-code-server-decide-what-workspace-or-folder-to-open)
- [How do I access my Documents/Downloads/Desktop folders in code-server on macOS?](#how-do-i-access-my-documentsdownloadsdesktop-folders-in-code-server-on-macos)
- [How do I direct server-side requests through a proxy?](#how-do-i-direct-server-side-requests-through-a-proxy)
- [How do I debug issues with code-server?](#how-do-i-debug-issues-with-code-server)
- [What is the healthz endpoint?](#what-is-the-healthz-endpoint)
- [What is the heartbeat file?](#what-is-the-heartbeat-file)
- [How do I change the password?](#how-do-i-change-the-password)
- [Can I store my password hashed?](#can-i-store-my-password-hashed)
- [Is multi-tenancy possible?](#is-multi-tenancy-possible)
- [Can I use Docker in a code-server container?](#can-i-use-docker-in-a-code-server-container)
- [How do I disable telemetry?](#how-do-i-disable-telemetry)
- [What's the difference between code-server and Coder?](#whats-the-difference-between-code-server-and-coder)
- [What's the difference between code-server and Theia?](#whats-the-difference-between-code-server-and-theia)
- [What's the difference between code-server and OpenVSCode-Server?](#whats-the-difference-between-code-server-and-openvscode-server)
- [What's the difference between code-server and GitHub Codespaces?](#whats-the-difference-between-code-server-and-github-codespaces)
- [What's the difference between code-server and VS Code web?](#whats-the-difference-between-code-server-and-vs-code-web)
- [Does code-server have any security login validation?](#does-code-server-have-any-security-login-validation)
- [Are there community projects involving code-server?](#are-there-community-projects-involving-code-server)
- [How do I change the port?](#how-do-i-change-the-port)
- [How do I hide the coder/coder promotion in Help: Getting Started?](#how-do-i-hide-the-codercoder-promotion-in-help-getting-started)
- [How do I disable the proxy?](#how-do-i-disable-the-proxy)
- [How do I disable file download?](#how-do-i-disable-file-download)
- [Why do web views not work?](#why-do-web-views-not-work)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
<!-- prettier-ignore-end -->

## Questions?

Please file all questions and support requests at
<https://github.com/coder/code-server/discussions>.

## How should I expose code-server to the internet?

Please see [our instructions on exposing code-server safely to the
internet](./guide.md).

## Can I use code-server on the iPad?

See [iPad](./ipad.md) for information on using code-server on the iPad.

## How does the config file work?

When `code-server` starts up, it creates a default config file in `~/.config/code-server/config.yaml`:

```yaml
bind-addr: 127.0.0.1:8080
auth: password
password: mew...22 # Randomly generated for each config.yaml
cert: false
```

The default config defines the following behavior:

- Listen on the loopback IP port 8080
- Enable password authorization
- Do not use TLS

Each key in the file maps directly to a `code-server` flag (run `code-server --help` to see a listing of all the flags). Any flags passed to `code-server`
will take priority over the config file.

You can change the config file's location using the `--config` flag or
`$CODE_SERVER_CONFIG` environment variable.

The default location respects `$XDG_CONFIG_HOME`.

## How do I make my keyboard shortcuts work?

Many shortcuts will not work by default, since they'll be "caught" by the browser.

If you use Chrome, you can work around this by installing the progressive web
app (PWA):

1. Start the editor
2. Click the **plus** icon in the URL toolbar to install the PWA

If you use Firefox, you can use the appropriate extension to install PWA.

1. Go to the installation [website](https://addons.mozilla.org/en-US/firefox/addon/pwas-for-firefox/) of the add-on
2. Add the add-on to Firefox
3. Follow the os-specific instructions on how to install the runtime counterpart

For other browsers, you'll have to remap keybindings for shortcuts to work.

## Why can't code-server use Microsoft's extension marketplace?

Though code-server takes the open-source core of VS Code and allows you to run
it in the browser, it is not entirely equivalent to Microsoft's VS Code.

One major difference is in regards to extensions and the marketplace. The core
of VS code is open source, while the marketplace and many published Microsoft
extensions are not. Furthermore, Microsoft prohibits the use of any
non-Microsoft VS Code from accessing their marketplace. Per the [Terms of
Service](https://cdn.vsassets.io/v/M146_20190123.39/_content/Microsoft-Visual-Studio-Marketplace-Terms-of-Use.pdf):

> Marketplace Offerings are intended for use only with Visual Studio Products
> and Services, and you may only install and use Marketplace Offer
Download .txt
gitextract_zegt8ql3/

├── .dockerignore
├── .editorconfig
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug-report.yml
│   │   ├── config.yml
│   │   ├── doc.md
│   │   └── feature-request.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── codecov.yml
│   ├── codeql-config.yml
│   ├── dependabot.yaml
│   ├── semantic.yaml
│   ├── stale.yml
│   └── workflows/
│       ├── build.yaml
│       ├── installer.yaml
│       ├── publish.yaml
│       ├── release.yaml
│       ├── scripts.yaml
│       ├── security.yaml
│       └── trivy-docker.yaml
├── .gitignore
├── .gitmodules
├── .node-version
├── .prettierignore
├── .prettierrc.yaml
├── .tours/
│   ├── contributing.tour
│   └── start-development.tour
├── CHANGELOG.md
├── LICENSE
├── ThirdPartyNotices.txt
├── ci/
│   ├── Caddyfile
│   ├── README.md
│   ├── build/
│   │   ├── build-code-server.sh
│   │   ├── build-lib.sh
│   │   ├── build-packages.sh
│   │   ├── build-release.sh
│   │   ├── build-standalone-release.sh
│   │   ├── build-vscode.sh
│   │   ├── clean.sh
│   │   ├── code-server-nfpm.sh
│   │   ├── code-server-user.service
│   │   ├── code-server.sh
│   │   ├── code-server@.service
│   │   ├── nfpm.yaml
│   │   └── npm-postinstall.sh
│   ├── dev/
│   │   ├── doctoc.sh
│   │   ├── gen_icons.sh
│   │   ├── lint-scripts.sh
│   │   ├── postinstall.sh
│   │   ├── preinstall.js
│   │   ├── test-e2e.sh
│   │   ├── test-integration.sh
│   │   ├── test-native.sh
│   │   ├── test-scripts.sh
│   │   ├── test-unit.sh
│   │   └── watch.ts
│   ├── helm-chart/
│   │   ├── .helmignore
│   │   ├── Chart.yaml
│   │   ├── templates/
│   │   │   ├── NOTES.txt
│   │   │   ├── _helpers.tpl
│   │   │   ├── deployment.yaml
│   │   │   ├── ingress.yaml
│   │   │   ├── pvc.yaml
│   │   │   ├── secrets.yaml
│   │   │   ├── service.yaml
│   │   │   ├── serviceaccount.yaml
│   │   │   └── tests/
│   │   │       └── test-connection.yaml
│   │   └── values.yaml
│   ├── lib.sh
│   ├── release-image/
│   │   ├── Dockerfile
│   │   ├── Dockerfile.fedora
│   │   ├── Dockerfile.opensuse
│   │   ├── docker-bake.hcl
│   │   ├── entrypoint-catatonit.sh
│   │   └── entrypoint.sh
│   └── steps/
│       ├── brew-bump.sh
│       ├── docker-buildx-push.sh
│       ├── publish-npm.sh
│       └── steps-lib.sh
├── docs/
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   ├── FAQ.md
│   ├── MAINTAINING.md
│   ├── README.md
│   ├── SECURITY.md
│   ├── android.md
│   ├── coder.md
│   ├── collaboration.md
│   ├── guide.md
│   ├── helm.md
│   ├── install.md
│   ├── ios.md
│   ├── ipad.md
│   ├── manifest.json
│   ├── npm.md
│   ├── requirements.md
│   ├── termux.md
│   ├── triage.md
│   └── upgrade.md
├── eslint.config.mjs
├── flake.nix
├── install.sh
├── package.json
├── patches/
│   ├── base-path.diff
│   ├── cli-window-open.diff
│   ├── clipboard.diff
│   ├── disable-builtin-ext-update.diff
│   ├── display-language.diff
│   ├── external-file-actions.diff
│   ├── fix-build.diff
│   ├── getting-started.diff
│   ├── insecure-notification.diff
│   ├── integration.diff
│   ├── keepalive.diff
│   ├── local-storage.diff
│   ├── logout.diff
│   ├── marketplace.diff
│   ├── proposed-api.diff
│   ├── proxy-uri.diff
│   ├── series
│   ├── service-worker.diff
│   ├── signature-verification.diff
│   ├── sourcemaps.diff
│   ├── store-socket.diff
│   ├── telemetry.diff
│   ├── trusted-domains.diff
│   ├── unique-db.diff
│   ├── update-check.diff
│   └── webview.diff
├── renovate.json
├── src/
│   ├── browser/
│   │   ├── pages/
│   │   │   ├── error.css
│   │   │   ├── error.html
│   │   │   ├── global.css
│   │   │   ├── login.css
│   │   │   └── login.html
│   │   ├── robots.txt
│   │   ├── security.txt
│   │   └── serviceWorker.ts
│   ├── common/
│   │   ├── emitter.ts
│   │   ├── http.ts
│   │   └── util.ts
│   └── node/
│       ├── app.ts
│       ├── cli.ts
│       ├── constants.ts
│       ├── entry.ts
│       ├── heart.ts
│       ├── http.ts
│       ├── i18n/
│       │   ├── index.ts
│       │   └── locales/
│       │       ├── en.json
│       │       ├── ja.json
│       │       ├── th.json
│       │       ├── ur.json
│       │       └── zh-cn.json
│       ├── main.ts
│       ├── proxy.ts
│       ├── routes/
│       │   ├── domainProxy.ts
│       │   ├── errors.ts
│       │   ├── health.ts
│       │   ├── index.ts
│       │   ├── login.ts
│       │   ├── logout.ts
│       │   ├── pathProxy.ts
│       │   ├── update.ts
│       │   └── vscode.ts
│       ├── settings.ts
│       ├── socket.ts
│       ├── update.ts
│       ├── util.ts
│       ├── vscodeSocket.ts
│       ├── wrapper.ts
│       └── wsRouter.ts
├── test/
│   ├── e2e/
│   │   ├── baseFixture.ts
│   │   ├── codeServer.test.ts
│   │   ├── downloads.test.ts
│   │   ├── extensions/
│   │   │   └── test-extension/
│   │   │       ├── .gitignore
│   │   │       ├── extension.ts
│   │   │       ├── package.json
│   │   │       └── tsconfig.json
│   │   ├── extensions.test.ts
│   │   ├── github.test.ts
│   │   ├── login.test.ts
│   │   ├── logout.test.ts
│   │   ├── models/
│   │   │   └── CodeServer.ts
│   │   ├── openHelpAbout.test.ts
│   │   ├── routes.test.ts
│   │   ├── terminal.test.ts
│   │   ├── uploads.test.ts
│   │   └── webview.test.ts
│   ├── integration/
│   │   ├── help.test.ts
│   │   └── installExtension.test.ts
│   ├── package.json
│   ├── playwright.config.ts
│   ├── scripts/
│   │   ├── build-lib.bats
│   │   ├── install.bats
│   │   └── steps-lib.bats
│   ├── tsconfig.json
│   ├── unit/
│   │   ├── common/
│   │   │   ├── emitter.test.ts
│   │   │   ├── http.test.ts
│   │   │   └── util.test.ts
│   │   ├── helpers.test.ts
│   │   └── node/
│   │       ├── app.test.ts
│   │       ├── cli.test.ts
│   │       ├── constants.test.ts
│   │       ├── heart.test.ts
│   │       ├── http.test.ts
│   │       ├── i18n.test.ts
│   │       ├── main.test.ts
│   │       ├── proxy.test.ts
│   │       ├── routes/
│   │       │   ├── errors.test.ts
│   │       │   ├── health.test.ts
│   │       │   ├── login.test.ts
│   │       │   ├── static.test.ts
│   │       │   └── vscode.test.ts
│   │       ├── settings.test.ts
│   │       ├── socket.test.ts
│   │       ├── update.test.ts
│   │       ├── util.test.ts
│   │       ├── vscodeSocket.test.ts
│   │       └── wrapper.test.ts
│   └── utils/
│       ├── constants.ts
│       ├── cssStub.ts
│       ├── globalE2eSetup.ts
│       ├── globalUnitSetup.ts
│       ├── helpers.ts
│       ├── httpserver.ts
│       ├── integration.ts
│       ├── runCodeServerCommand.ts
│       └── wtfnode.ts
├── tsconfig.json
└── typings/
    └── httpolyglot/
        └── index.d.ts
Download .txt
SYMBOL INDEX (231 symbols across 39 files)

FILE: ci/dev/watch.ts
  type DevelopmentCompilers (line 5) | interface DevelopmentCompilers {
  class Watcher (line 13) | class Watcher {
    method initialize (line 55) | public async initialize(): Promise<void> {
    method dispose (line 121) | private dispose(code: number | null): void {
  function main (line 133) | async function main(): Promise<void> {

FILE: src/common/emitter.ts
  type Callback (line 7) | type Callback<T, R = void | Promise<void>> = (t: T, p: Promise<void>) => R
  type Disposable (line 9) | interface Disposable {
  type Event (line 13) | interface Event<T> {
  class Emitter (line 20) | class Emitter<T> {
    method event (line 23) | public get event(): Event<T> {
    method emit (line 41) | public async emit(value: T): Promise<void> {
    method dispose (line 58) | public dispose(): void {

FILE: src/common/http.ts
  type HttpCode (line 1) | enum HttpCode {
  class HttpError (line 16) | class HttpError extends Error {
    method constructor (line 17) | public constructor(
  function getCookieSessionName (line 27) | function getCookieSessionName(suffix?: string): string {

FILE: src/common/util.ts
  function logError (line 29) | function logError(logger: { error: (msg: string) => void }, prefix: stri...

FILE: src/node/app.ts
  type SocketOptions (line 15) | type SocketOptions = { socket: string; "socket-mode"?: string }
  type ListenOptions (line 16) | type ListenOptions = DefaultedArgs | SocketOptions
  type App (line 18) | interface App extends Disposable {

FILE: src/node/cli.ts
  type Feature (line 8) | enum Feature {
  type AuthType (line 13) | enum AuthType {
  class Optional (line 18) | class Optional<T> {
    method constructor (line 19) | public constructor(public readonly value?: T) {}
  type LogLevel (line 22) | enum LogLevel {
  class OptionalString (line 30) | class OptionalString extends Optional<string> {}
  type UserProvidedCodeArgs (line 35) | interface UserProvidedCodeArgs {
  type UserProvidedArgs (line 68) | interface UserProvidedArgs extends UserProvidedCodeArgs {
  type Option (line 103) | interface Option<T> {
  type OptionType (line 124) | type OptionType<T> = T extends boolean
  type Options (line 140) | type Options<T> = {
  type DefaultedArgs (line 508) | interface DefaultedArgs extends ConfigArgs {
  function setDefaults (line 532) | async function setDefaults(cliArgs: UserProvidedArgs, configArgs?: Confi...
  function getResolvedPathsFromArgs (line 682) | function getResolvedPathsFromArgs(args: UserProvidedArgs): string[] {
  function defaultConfigFile (line 697) | function defaultConfigFile(password: string): string {
  type ConfigArgs (line 705) | interface ConfigArgs extends UserProvidedArgs {
  function readConfigFile (line 714) | async function readConfigFile(configPath?: string): Promise<ConfigArgs> {
  function parseConfigFile (line 745) | function parseConfigFile(configFile: string, configPath: string): Config...
  function parseBindAddr (line 778) | function parseBindAddr(bindAddr: string): Addr {
  type Addr (line 789) | interface Addr {
  function bindAddrFromArgs (line 798) | function bindAddrFromArgs(addr: Addr, args: UserProvidedArgs): Addr {
  function bindAddrFromAllSources (line 819) | function bindAddrFromAllSources(...argsConfig: UserProvidedArgs[]): Addr {
  type CodeArgs (line 891) | interface CodeArgs extends UserProvidedCodeArgs {

FILE: src/node/constants.ts
  function getPackageJson (line 6) | function getPackageJson(relativePath: string): JSONSchemaForNPMPackageJs...
  constant PACKAGE_JSON (line 19) | const PACKAGE_JSON = "package.json"
  function getVersionString (line 34) | function getVersionString(): string {
  function getVersionJsonString (line 42) | function getVersionJsonString(): string {

FILE: src/node/entry.ts
  function entry (line 7) | async function entry(): Promise<void> {

FILE: src/node/heart.ts
  class Heart (line 8) | class Heart {
    method constructor (line 16) | public constructor(
    method setState (line 24) | private setState(state: typeof this.state) {
    method alive (line 31) | public alive(): boolean {
    method beat (line 40) | public async beat(): Promise<void> {
    method dispose (line 77) | public dispose(): void {

FILE: src/node/http.ts
  type ClientConfiguration (line 27) | interface ClientConfiguration {
  type Request (line 38) | interface Request {
  function disposer (line 251) | function disposer(server: http.Server): Disposable["dispose"] {
  function getFirstHeader (line 334) | function getFirstHeader(req: http.IncomingMessage, headerName: string): ...
  function ensureOrigin (line 342) | function ensureOrigin(req: express.Request, _?: express.Response, next?:...
  function authenticateOrigin (line 357) | function authenticateOrigin(req: express.Request): void {
  function getHost (line 395) | function getHost(req: express.Request): string | undefined {

FILE: src/node/i18n/index.ts
  function loadCustomStrings (line 27) | async function loadCustomStrings(filePath: string): Promise<void> {

FILE: src/node/main.ts
  type OpenCommandPipeArgs (line 37) | interface OpenCommandPipeArgs {

FILE: src/node/routes/errors.ts
  type ErrorWithStatusCode (line 11) | interface ErrorWithStatusCode {
  type ErrorWithCode (line 15) | interface ErrorWithCode {

FILE: src/node/routes/login.ts
  class RateLimiter (line 12) | class RateLimiter {
    method canTry (line 16) | public canTry(): boolean {
    method removeToken (line 23) | public removeToken(): boolean {

FILE: src/node/routes/pathProxy.ts
  function proxy (line 24) | async function proxy(
  function wsProxy (line 58) | async function wsProxy(

FILE: src/node/routes/vscode.ts
  type IVSCodeServerAPI (line 27) | interface IVSCodeServerAPI {
  type VSCodeModule (line 42) | type VSCodeModule = {
  function loadVSCode (line 55) | async function loadVSCode(req: express.Request): Promise<IVSCodeServerAP...
  function dispose (line 255) | function dispose() {

FILE: src/node/settings.ts
  type Settings (line 5) | type Settings = { [key: string]: Settings | string | boolean | number }
  class SettingsProvider (line 10) | class SettingsProvider<T> {
    method constructor (line 11) | public constructor(private readonly settingsPath: string) {}
    method read (line 17) | public async read(): Promise<T> {
    method write (line 33) | public async write(settings: Partial<T>): Promise<void> {
  type UpdateSettings (line 44) | interface UpdateSettings {
  type CoderSettings (line 54) | interface CoderSettings extends UpdateSettings {

FILE: src/node/socket.ts
  class SocketProxyProvider (line 14) | class SocketProxyProvider {
    method stop (line 23) | public stop(): void {
    method createProxy (line 37) | public async createProxy(socket: tls.TLSSocket | net.Socket | stream.D...
    method startProxyServer (line 77) | private async startProxyServer(): Promise<net.Server> {
    method findFreeSocketPath (line 98) | public async findFreeSocketPath(basePath: string, maxTries = 100): Pro...

FILE: src/node/update.ts
  type Update (line 10) | interface Update {
  type LatestResponse (line 15) | interface LatestResponse {
  class UpdateProvider (line 22) | class UpdateProvider {
    method constructor (line 26) | public constructor(
    method getUpdate (line 41) | public async getUpdate(force?: boolean): Promise<Update> {
    method _getUpdate (line 51) | private async _getUpdate(force?: boolean): Promise<Update> {
    method isLatestVersion (line 75) | public isLatestVersion(latest: Update): boolean {
    method request (line 84) | private async request(uri: string): Promise<Buffer> {
    method requestResponse (line 100) | private async requestResponse(uri: string): Promise<http.IncomingMessa...

FILE: src/node/util.ts
  type Paths (line 13) | interface Paths {
  type OnLineCallback (line 26) | type OnLineCallback = (strippedLine: string, originalLine: string) => void
  function getEnvPaths (line 59) | function getEnvPaths(platform = process.platform): Paths {
  type PasswordMethod (line 177) | type PasswordMethod = "SHA256" | "ARGON2" | "PLAIN_TEXT"
  function getPasswordMethod (line 189) | function getPasswordMethod(hashedPassword: string | undefined): Password...
  type PasswordValidation (line 203) | type PasswordValidation = {
  type HandlePasswordValidationArgs (line 208) | type HandlePasswordValidationArgs = {
  function handlePasswordValidation (line 223) | async function handlePasswordValidation({
  type IsCookieValidArgs (line 264) | type IsCookieValidArgs = {
  function isCookieValid (line 272) | async function isCookieValid({
  function sanitizeString (line 298) | function sanitizeString(str: unknown): string {
  type OpenOptions (line 392) | interface OpenOptions {
  function constructOpenOptions (line 407) | function constructOpenOptions(platform: NodeJS.Platform | "wsl", urlSear...
  function canConnect (line 450) | function canConnect(path: string): Promise<boolean> {
  function escapeHtml (line 484) | function escapeHtml(unsafe: string): string {
  function isNodeJSErrnoException (line 498) | function isNodeJSErrnoException(error: unknown): error is NodeJS.ErrnoEx...
  function splitOnFirstEquals (line 510) | function splitOnFirstEquals(str: string): [string, string | undefined] {

FILE: src/node/vscodeSocket.ts
  type EditorSessionEntry (line 10) | interface EditorSessionEntry {
  type DeleteSessionRequest (line 23) | interface DeleteSessionRequest {
  type AddSessionRequest (line 27) | interface AddSessionRequest {
  type GetSessionResponse (line 31) | interface GetSessionResponse {
  function makeEditorSessionManagerServer (line 35) | async function makeEditorSessionManagerServer(
  class EditorSessionManager (line 85) | class EditorSessionManager {
    method addSession (line 89) | addSession(entry: EditorSessionEntry): void {
    method getCandidatesForFile (line 94) | getCandidatesForFile(filePath: string): EditorSessionEntry[] {
    method deleteSession (line 122) | deleteSession(socketPath: string): void {
    method getConnectedSocketPath (line 131) | async getConnectedSocketPath(filePath: string): Promise<string | undef...
  class EditorSessionManagerClient (line 147) | class EditorSessionManagerClient {
    method constructor (line 148) | constructor(private codeServerSocketPath: string) {}
    method canConnect (line 150) | async canConnect() {
    method getConnectedSocketPath (line 154) | async getConnectedSocketPath(filePath: string): Promise<string | undef...
    method addSession (line 187) | async addSession(request: AddSessionRequest): Promise<void> {

FILE: src/node/wrapper.ts
  function onMessage (line 18) | function onMessage<M, T extends M>(
  type ParentHandshakeMessage (line 63) | interface ParentHandshakeMessage {
  type ChildHandshakeMessage (line 68) | interface ChildHandshakeMessage {
  type RelaunchMessage (line 72) | interface RelaunchMessage {
  type ChildMessage (line 77) | type ChildMessage = RelaunchMessage | ChildHandshakeMessage
  type ParentMessage (line 78) | type ParentMessage = ParentHandshakeMessage
  class ProcessError (line 80) | class ProcessError extends Error {
    method constructor (line 81) | public constructor(
  method constructor (line 111) | public constructor() {
  method preventExit (line 130) | public preventExit(): void {
  method exit (line 141) | public exit(error?: number | ProcessError): never {
  class ChildProcess (line 154) | class ChildProcess extends Process {
    method constructor (line 157) | public constructor(private readonly parentPid: number) {
    method handshake (line 178) | public async handshake(): Promise<DefaultedArgs> {
    method relaunch (line 201) | public relaunch(version: string): void {
    method send (line 208) | private send(message: ChildMessage): void {
  class ParentProcess (line 222) | class ParentProcess extends Process {
    method constructor (line 235) | public constructor(private currentVersion: string) {
    method disposeChild (line 272) | private async disposeChild(): Promise<void> {
    method relaunch (line 284) | private async relaunch(): Promise<void> {
    method start (line 295) | public start(args: DefaultedArgs): Promise<void> {
    method _start (line 308) | private async _start(): Promise<void> {
    method spawn (line 336) | private spawn(): cp.ChildProcess {
    method handshake (line 350) | private async handshake(child: cp.ChildProcess): Promise<void> {
    method send (line 368) | private send(child: cp.ChildProcess, message: ParentMessage): void {
  function isChild (line 381) | function isChild(proc: ChildProcess | ParentProcess): proc is ChildProce...

FILE: src/node/wsRouter.ts
  type WebsocketRequest (line 7) | interface WebsocketRequest extends express.Request {
  type InternalWebsocketRequest (line 12) | interface InternalWebsocketRequest extends WebsocketRequest {
  type WebSocketHandler (line 34) | type WebSocketHandler = (
  class WebsocketRouter (line 40) | class WebsocketRouter {
    method ws (line 50) | public ws(route: expressCore.PathParams, ...handlers: WebSocketHandler...
  function Router (line 64) | function Router(): WebsocketRouter {

FILE: test/e2e/baseFixture.ts
  type TestFixtures (line 40) | interface TestFixtures {

FILE: test/e2e/extensions.test.ts
  function runTestExtensionTests (line 6) | function runTestExtensionTests() {

FILE: test/e2e/extensions/test-extension/extension.ts
  function activate (line 3) | function activate(context: vscode.ExtensionContext) {

FILE: test/e2e/models/CodeServer.ts
  type CodeServerProcess (line 12) | interface CodeServerProcess {
  class Context (line 17) | class Context {
    method canceled (line 20) | public canceled(): boolean {
    method finished (line 23) | public finished(): boolean {
    method cancel (line 26) | public cancel(): void {
    method finish (line 29) | public finish(): void {
  class CodeServer (line 37) | class CodeServer {
    method constructor (line 42) | constructor(
    method address (line 56) | async address(): Promise<string> {
    method workspaceDir (line 68) | get workspaceDir(): Promise<string> | string {
    method createWorkspace (line 78) | private async createWorkspace(): Promise<string> {
    method spawn (line 119) | private async spawn(): Promise<CodeServerProcess> {
    method run (line 205) | async run(args: string[]): Promise<void> {
    method argsWithDefaults (line 223) | private async argsWithDefaults(args: string[]): Promise<string[]> {
    method close (line 245) | async close(): Promise<void> {
    method authEnabled (line 257) | authEnabled(): boolean {
  class CodeServerPage (line 269) | class CodeServerPage {
    method constructor (line 272) | constructor(
    method address (line 284) | address() {
    method workspaceDir (line 291) | get workspaceDir() {
    method navigate (line 299) | async navigate(endpoint = "/") {
    method reloadUntilEditorIsReady (line 320) | async reloadUntilEditorIsReady() {
    method isEditorVisible (line 351) | async isEditorVisible() {
    method waitForTestExtensionLoaded (line 365) | async waitForTestExtensionLoaded(): Promise<void> {
    method focusTerminal (line 379) | async focusTerminal() {
    method openFile (line 403) | async openFile(file: string) {
    method openFileExternally (line 412) | async openFileExternally(file: string) {
    method waitForTab (line 419) | async waitForTab(file: string): Promise<void> {
    method tabIsVisible (line 426) | async tabIsVisible(file: string): Promise<boolean> {
    method executeCommandViaMenus (line 434) | async executeCommandViaMenus(command: string) {
    method navigateItems (line 447) | async navigateItems(items: string[], selector: string, open?: (selecto...
    method navigateQuickInput (line 545) | async navigateQuickInput(items: string[]): Promise<void> {
    method navigateMenus (line 552) | async navigateMenus(menus: string[]): Promise<void> {
    method openContextMenu (line 561) | async openContextMenu(selector: string): Promise<void> {
    method exec (line 570) | async exec(command: string): Promise<void> {
    method installExtension (line 580) | async installExtension(id: string): Promise<void> {
    method stateFlush (line 590) | async stateFlush(): Promise<void> {

FILE: test/e2e/routes.test.ts
  constant CODE_WORKSPACE_DIR (line 55) | const CODE_WORKSPACE_DIR = process.env.CODE_WORKSPACE_DIR || ""
  constant CODE_FOLDER_DIR (line 65) | const CODE_FOLDER_DIR = process.env.CODE_FOLDER_DIR || ""

FILE: test/unit/common/util.test.ts
  type LocationLike (line 9) | type LocationLike = Pick<Location, "pathname" | "origin">

FILE: test/unit/node/app.test.ts
  function masterBall (line 84) | async function masterBall() {

FILE: test/unit/node/routes/errors.test.ts
  function createRequest (line 58) | async function createRequest(args: UserProvidedArgs = {}): Promise<expre...

FILE: test/unit/node/routes/login.test.ts
  function codeServer (line 46) | function codeServer(): httpserver.HttpServer {

FILE: test/unit/node/routes/static.test.ts
  constant NOT_FOUND (line 8) | const NOT_FOUND = {
  function codeServer (line 15) | function codeServer(): httpserver.HttpServer {
  function commonTests (line 43) | function commonTests() {

FILE: test/utils/constants.ts
  constant PASSWORD (line 1) | const PASSWORD = "e45432jklfdsab"
  constant REVERSE_PROXY_BASE_PATH (line 3) | const REVERSE_PROXY_BASE_PATH = process.env.CS_TEST_REVERSE_PROXY_BASE_P...
  constant REVERSE_PROXY_PORT (line 4) | const REVERSE_PROXY_PORT = process.env.CS_TEST_REVERSE_PROXY_PORT || "8000"

FILE: test/utils/helpers.ts
  function mockLogger (line 13) | function mockLogger() {
  function clean (line 32) | async function clean(testName: string): Promise<void> {
  function tmpdir (line 42) | async function tmpdir(testName: string): Promise<string> {
  function useEnv (line 55) | function useEnv(key: string): [(nextValue: string | undefined) => string...
  function idleTimer (line 97) | function idleTimer(message: string, reject: (error: Error) => void, dela...
  function getMaybeProxiedCodeServer (line 116) | async function getMaybeProxiedCodeServer(codeServer: CodeServerPage | Co...
  function getMaybeProxiedPathname (line 130) | function getMaybeProxiedPathname(url: URL): string {
  type FakeVscodeSockets (line 140) | interface FakeVscodeSockets {
  function listenOn (line 151) | function listenOn(...socketPaths: string[]): FakeVscodeSockets {

FILE: test/utils/httpserver.ts
  class HttpServer (line 13) | class HttpServer {
    method constructor (line 23) | public constructor(server?: { server: http.Server; dispose: Disposable...
    method listen (line 32) | public listen(fn: http.RequestListener): Promise<void> {
    method listenUpgrade (line 53) | public listenUpgrade(app: express.Express): void {
    method fetch (line 61) | public fetch(requestPath: string, opts?: RequestInit, query?: { [key: ...
    method ws (line 78) | public ws(requestPath: string, options?: Websocket.ClientOptions): Web...
    method wsWait (line 91) | public wsWait(requestPath: string, options?: Websocket.ClientOptions):...
    method port (line 99) | public port(): number {

FILE: test/utils/integration.ts
  function setup (line 9) | async function setup(argv: string[], configFile?: string): Promise<https...

FILE: test/utils/runCodeServerCommand.ts
  function runCodeServerCommand (line 9) | async function runCodeServerCommand(

FILE: test/utils/wtfnode.ts
  function setup (line 21) | function setup(): void {
Condensed preview — 232 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (886K chars).
[
  {
    "path": ".dockerignore",
    "chars": 25,
    "preview": "**\n!release-packages\n!ci\n"
  },
  {
    "path": ".editorconfig",
    "chars": 86,
    "preview": "root = true\n\n[*]\nindent_style = space\ntrim_trailing_whitespace = true\nindent_size = 2\n"
  },
  {
    "path": ".git-blame-ignore-revs",
    "chars": 57,
    "preview": "# Prettier 3.4.2\n9b0340a09276f93c054d705d1b9a5f24cc5dbc97"
  },
  {
    "path": ".gitattributes",
    "chars": 47,
    "preview": "*.afdesign filter=lfs diff=lfs merge=lfs -text\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 144,
    "preview": "* @coder/code-server\n\nci/helm-chart/ @Matthew-Beckett @alexgorbatchev\n\ndocs/install.md @GNUxeava\n\nsrc/node/i18n/locales/"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "chars": 4179,
    "preview": "name: Bug report\ndescription: File a bug report\nlabels: [\"bug\", \"triage\"]\nbody:\n  - type: checkboxes\n    attributes:\n   "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 436,
    "preview": "blank_issues_enabled: false\ncontact_links:\n  - name: Question?\n    url: https://github.com/coder/code-server/discussions"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/doc.md",
    "chars": 215,
    "preview": "---\nname: Documentation improvement\nabout: Suggest a documentation improvement\nlabels: \"docs\"\n---\n\n## What is your sugge"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-request.md",
    "chars": 274,
    "preview": "---\nname: Feature request\nabout: Suggest an idea to improve code-server\nlabels: enhancement\n---\n\n## What is your suggest"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 200,
    "preview": "<!--\nPlease link to the issue this PR solves.\nIf there is no existing issue, please first create one unless the fix is m"
  },
  {
    "path": ".github/codecov.yml",
    "chars": 674,
    "preview": "codecov:\n  require_ci_to_pass: yes\n  allow_coverage_offsets: True\n\ncoverage:\n  precision: 2\n  round: down\n  range: \"40.."
  },
  {
    "path": ".github/codeql-config.yml",
    "chars": 34,
    "preview": "name: \"code-server CodeQL config\"\n"
  },
  {
    "path": ".github/dependabot.yaml",
    "chars": 801,
    "preview": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"monthly\"\n "
  },
  {
    "path": ".github/semantic.yaml",
    "chars": 1904,
    "preview": "###############################################################################\n# This file configures \"Semantic Pull Re"
  },
  {
    "path": ".github/stale.yml",
    "chars": 545,
    "preview": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 180\n# Number of days of inactivity before a"
  },
  {
    "path": ".github/workflows/build.yaml",
    "chars": 9758,
    "preview": "name: Build\n\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n\n# Cancel in-progress run"
  },
  {
    "path": ".github/workflows/installer.yaml",
    "chars": 1977,
    "preview": "name: Installer integration\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - \"install.sh\"\n      - \".github/wor"
  },
  {
    "path": ".github/workflows/publish.yaml",
    "chars": 5169,
    "preview": "name: Publish code-server\n\non:\n  # Shows the manual trigger in GitHub UI\n  # helpful as a back-up in case the GitHub Act"
  },
  {
    "path": ".github/workflows/release.yaml",
    "chars": 9826,
    "preview": "name: Draft release\n\non:\n  workflow_dispatch:\n    inputs:\n      version:\n        description: The version to publish (in"
  },
  {
    "path": ".github/workflows/scripts.yaml",
    "chars": 1557,
    "preview": "name: Script unit tests\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - \"**.sh\"\n      - \"**.bats\"\n  pull_requ"
  },
  {
    "path": ".github/workflows/security.yaml",
    "chars": 2580,
    "preview": "name: Security\n\non:\n  push:\n    branches: [main]\n    paths:\n      - \"package.json\"\n  pull_request:\n    paths:\n      - \"p"
  },
  {
    "path": ".github/workflows/trivy-docker.yaml",
    "chars": 1782,
    "preview": "name: Trivy Nightly Docker Scan\n\non:\n  # Run scans if the workflow is modified, in order to test the\n  # workflow itself"
  },
  {
    "path": ".gitignore",
    "chars": 356,
    "preview": ".tsbuildinfo\n.cache\n/out*/\nrelease/\nrelease-npm-package/\nrelease-standalone/\nrelease-packages/\nrelease-gcp/\nrelease-imag"
  },
  {
    "path": ".gitmodules",
    "chars": 87,
    "preview": "[submodule \"lib/vscode\"]\n\tpath = lib/vscode\n\turl = https://github.com/microsoft/vscode\n"
  },
  {
    "path": ".node-version",
    "chars": 8,
    "preview": "22.22.0\n"
  },
  {
    "path": ".prettierignore",
    "chars": 165,
    "preview": "lib/vscode\nlib/vscode-reh-web-linux-x64\nrelease-standalone\nrelease-packages\nrelease\nhelm-chart\ntest/scripts\ntest/e2e/ext"
  },
  {
    "path": ".prettierrc.yaml",
    "chars": 101,
    "preview": "printWidth: 120\nsemi: false\ntrailingComma: all\narrowParens: always\nsingleQuote: false\nuseTabs: false\n"
  },
  {
    "path": ".tours/contributing.tour",
    "chars": 6992,
    "preview": "{\n  \"$schema\": \"https://aka.ms/codetour-schema\",\n  \"title\": \"Contributing\",\n  \"steps\": [\n    {\n      \"directory\": \"src\","
  },
  {
    "path": ".tours/start-development.tour",
    "chars": 2499,
    "preview": "{\n  \"$schema\": \"https://aka.ms/codetour-schema\",\n  \"title\": \"Start Development\",\n  \"steps\": [\n    {\n      \"file\": \"packa"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 32993,
    "preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
  },
  {
    "path": "LICENSE",
    "chars": 1084,
    "preview": "The MIT License\n\nCopyright (c) 2019 Coder Technologies Inc.\n\nPermission is hereby granted, free of charge, to any person"
  },
  {
    "path": "ThirdPartyNotices.txt",
    "chars": 1356,
    "preview": "code-server\n\nTHIRD-PARTY SOFTWARE NOTICES AND INFORMATION\nDo Not Translate or Localize\n\n1.\tMicrosoft/vscode version 1.47"
  },
  {
    "path": "ci/Caddyfile",
    "chars": 282,
    "preview": "{\n\tadmin    localhost:4444\n}\n:8000 {\n\t@portLocalhost path_regexp port ^/([0-9]+)\\/ide\n        handle @portLocalhost {\n\t\t"
  },
  {
    "path": "ci/README.md",
    "chars": 5425,
    "preview": "# ci\n\nThis directory contains scripts used for code-server's continuous integration infrastructure.\n\nSome of these scrip"
  },
  {
    "path": "ci/build/build-code-server.sh",
    "chars": 463,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Builds code-server into out and the frontend into dist.\n\nmain() {\n  cd \"$(dirna"
  },
  {
    "path": "ci/build/build-lib.sh",
    "chars": 763,
    "preview": "#!/usr/bin/env bash\n\n# This is a library which contains functions used inside ci/build\n#\n# We separated it into it's own"
  },
  {
    "path": "ci/build/build-packages.sh",
    "chars": 2026,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Given a platform-specific release found in ./release-standalone, generate an\n# "
  },
  {
    "path": "ci/build/build-release.sh",
    "chars": 4524,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Once both code-server and VS Code have been built, use this script to copy\n# th"
  },
  {
    "path": "ci/build/build-standalone-release.sh",
    "chars": 1125,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Once we have an NPM package, use this script to copy it to a separate\n# directo"
  },
  {
    "path": "ci/build/build-vscode.sh",
    "chars": 5716,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Builds vscode into lib/vscode/out-vscode.\n\n# MINIFY controls whether a minified"
  },
  {
    "path": "ci/build/clean.sh",
    "chars": 132,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nmain() {\n  cd \"$(dirname \"${0}\")/../..\"\n  source ./ci/lib.sh\n\n  git clean -Xffd\n}"
  },
  {
    "path": "ci/build/code-server-nfpm.sh",
    "chars": 66,
    "preview": "#!/usr/bin/env sh\n\nexec /usr/lib/code-server/bin/code-server \"$@\"\n"
  },
  {
    "path": "ci/build/code-server-user.service",
    "chars": 154,
    "preview": "[Unit]\nDescription=code-server\nAfter=network.target\n\n[Service]\nType=exec\nExecStart=/usr/bin/code-server\nRestart=always\n\n"
  },
  {
    "path": "ci/build/code-server.sh",
    "chars": 603,
    "preview": "#!/bin/sh\nset -eu\n\n# This script is intended to be bundled into the standalone releases.\n# Runs code-server with the bun"
  },
  {
    "path": "ci/build/code-server@.service",
    "chars": 162,
    "preview": "[Unit]\nDescription=code-server\nAfter=network.target\n\n[Service]\nType=exec\nExecStart=/usr/bin/code-server\nRestart=always\nU"
  },
  {
    "path": "ci/build/nfpm.yaml",
    "chars": 624,
    "preview": "name: \"code-server\"\narch: \"${NFPM_ARCH}\"\nplatform: \"linux\"\nversion: \"v${VERSION}\"\nsection: \"devel\"\npriority: \"optional\"\n"
  },
  {
    "path": "ci/build/npm-postinstall.sh",
    "chars": 4793,
    "preview": "#!/usr/bin/env sh\nset -eu\n\n# Copied from ../lib.sh except we do not rename Darwin and we do not need to\n# detect Alpine."
  },
  {
    "path": "ci/dev/doctoc.sh",
    "chars": 952,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nmain() {\n  cd \"$(dirname \"$0\")/../..\"\n\n  doctoc --title '# FAQ' docs/FAQ.md > /de"
  },
  {
    "path": "ci/dev/gen_icons.sh",
    "chars": 2123,
    "preview": "#!/bin/sh\nset -eu\n\n# Generate icons from a single favicon.svg.  favicon.svg should have no fill\n# colors set.\nmain() {\n "
  },
  {
    "path": "ci/dev/lint-scripts.sh",
    "chars": 194,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nmain() {\n  cd \"$(dirname \"$0\")/../..\"\n  shellcheck -e SC2046,SC2164,SC2154,SC1091"
  },
  {
    "path": "ci/dev/postinstall.sh",
    "chars": 920,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Install dependencies in $1.\ninstall-deps() {\n  local args=()\n  if [[ ${CI-} ]];"
  },
  {
    "path": "ci/dev/preinstall.js",
    "chars": 136,
    "preview": "if (process.env.npm_execpath.includes(\"yarn\")) {\n  throw new Error(\"`yarn` is no longer supported; please use `npm insta"
  },
  {
    "path": "ci/dev/test-e2e.sh",
    "chars": 1202,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nhelp() {\n  echo >&2 \"  You can build with 'npm run watch' or you can build a rele"
  },
  {
    "path": "ci/dev/test-integration.sh",
    "chars": 1165,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nhelp() {\n  echo >&2 \"  You can build the standalone release with 'npm run release"
  },
  {
    "path": "ci/dev/test-native.sh",
    "chars": 1123,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nhelp() {\n  echo >&2 \"  You can build the standalone release with 'npm run release"
  },
  {
    "path": "ci/dev/test-scripts.sh",
    "chars": 112,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nmain() {\n  cd \"$(dirname \"$0\")/../..\"\n  bats ./test/scripts\n}\n\nmain \"$@\"\n"
  },
  {
    "path": "ci/dev/test-unit.sh",
    "chars": 369,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nmain() {\n  cd \"$(dirname \"$0\")/../..\"\n\n  source ./ci/lib.sh\n\n  # We must keep jes"
  },
  {
    "path": "ci/dev/watch.ts",
    "chars": 4156,
    "preview": "import { spawn, ChildProcess } from \"child_process\"\nimport * as path from \"path\"\nimport { onLine, OnLineCallback } from "
  },
  {
    "path": "ci/helm-chart/.helmignore",
    "chars": 349,
    "preview": "# Patterns to ignore when building packages.\n# This supports shell glob matching, relative path matching, and\n# negation"
  },
  {
    "path": "ci/helm-chart/Chart.yaml",
    "chars": 1111,
    "preview": "apiVersion: v2\nname: code-server\ndescription: A Helm chart for coder/code-server\n\n# A chart can be either an 'applicatio"
  },
  {
    "path": "ci/helm-chart/templates/NOTES.txt",
    "chars": 1572,
    "preview": "1. Get the application URL by running these commands:\n{{- if .Values.ingress.enabled }}\n{{- range $host := .Values.ingre"
  },
  {
    "path": "ci/helm-chart/templates/_helpers.tpl",
    "chars": 1885,
    "preview": "{{/* vim: set filetype=mustache: */}}\n{{/*\nExpand the name of the chart.\n*/}}\n{{- define \"code-server.name\" -}}\n{{- defa"
  },
  {
    "path": "ci/helm-chart/templates/deployment.yaml",
    "chars": 6435,
    "preview": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: {{ include \"code-server.fullname\" . }}\n  labels:\n    {{- include "
  },
  {
    "path": "ci/helm-chart/templates/ingress.yaml",
    "chars": 1755,
    "preview": "{{- if .Values.ingress.enabled -}}\n{{- $fullName := include \"code-server.fullname\" . -}}\n{{- $svcPort := .Values.service"
  },
  {
    "path": "ci/helm-chart/templates/pvc.yaml",
    "chars": 799,
    "preview": "{{- if and (and .Values.persistence.enabled (not .Values.persistence.existingClaim)) (not .Values.persistence.hostPath) "
  },
  {
    "path": "ci/helm-chart/templates/secrets.yaml",
    "chars": 412,
    "preview": "{{- if not .Values.existingSecret }}\napiVersion: v1\nkind: Secret\nmetadata:\n  name: {{ include \"code-server.fullname\" . }"
  },
  {
    "path": "ci/helm-chart/templates/service.yaml",
    "chars": 583,
    "preview": "apiVersion: v1\nkind: Service\nmetadata:\n  name: {{ include \"code-server.fullname\" . }}\n  labels:\n    {{- include \"code-se"
  },
  {
    "path": "ci/helm-chart/templates/serviceaccount.yaml",
    "chars": 224,
    "preview": "{{- if or .Values.serviceAccount.create -}}\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  labels:\n    {{- include \"cod"
  },
  {
    "path": "ci/helm-chart/templates/tests/test-connection.yaml",
    "chars": 400,
    "preview": "apiVersion: v1\nkind: Pod\nmetadata:\n  name: \"{{ include \"code-server.fullname\" . }}-test-connection\"\n  labels:\n    {{- in"
  },
  {
    "path": "ci/helm-chart/values.yaml",
    "chars": 5949,
    "preview": "# Default values for code-server.\n# This is a YAML-formatted file.\n# Declare variables to be passed into your templates."
  },
  {
    "path": "ci/lib.sh",
    "chars": 1077,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\npushd() {\n  builtin pushd \"$@\" > /dev/null\n}\n\npopd() {\n  builtin popd > /dev/null"
  },
  {
    "path": "ci/release-image/Dockerfile",
    "chars": 1792,
    "preview": "# syntax=docker/dockerfile:experimental\n\nARG BASE=debian:12\nFROM scratch AS packages\nCOPY release-packages/code-server*."
  },
  {
    "path": "ci/release-image/Dockerfile.fedora",
    "chars": 1624,
    "preview": "# syntax=docker/dockerfile:experimental\n\nARG BASE=fedora:39\nFROM scratch AS packages\nCOPY release-packages/code-server*."
  },
  {
    "path": "ci/release-image/Dockerfile.opensuse",
    "chars": 1668,
    "preview": "# syntax=docker/dockerfile:experimental\n\nARG BASE=opensuse/tumbleweed\nFROM scratch AS packages\nCOPY release-packages/cod"
  },
  {
    "path": "ci/release-image/docker-bake.hcl",
    "chars": 2854,
    "preview": "# Use this file from the top of the repo, with `-f ci/release-image/docker-bake.hcl`\n\n# Uses env var VERSION if set;\n# n"
  },
  {
    "path": "ci/release-image/entrypoint-catatonit.sh",
    "chars": 970,
    "preview": "#!/bin/sh\nset -eu\n\n# We do this first to ensure sudo works below when renaming the user.\n# Otherwise the current contain"
  },
  {
    "path": "ci/release-image/entrypoint.sh",
    "chars": 978,
    "preview": "#!/bin/sh\nset -eu\n\n# We do this first to ensure sudo works below when renaming the user.\n# Otherwise the current contain"
  },
  {
    "path": "ci/steps/brew-bump.sh",
    "chars": 1001,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nmain() {\n  # Only sourcing this so we get access to $VERSION\n  source ./ci/lib.sh"
  },
  {
    "path": "ci/steps/docker-buildx-push.sh",
    "chars": 402,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nmain() {\n  cd \"$(dirname \"$0\")/../..\"\n  # NOTE@jsjoeio - this script assumes VERS"
  },
  {
    "path": "ci/steps/publish-npm.sh",
    "chars": 5730,
    "preview": "#!/usr/bin/env bash\nset -euo pipefail\n\nmain() {\n  cd \"$(dirname \"$0\")/../..\"\n  source ./ci/lib.sh\n  source ./ci/steps/st"
  },
  {
    "path": "ci/steps/steps-lib.sh",
    "chars": 890,
    "preview": "#!/usr/bin/env bash\n\n# This is a library which contains functions used inside ci/steps\n#\n# We separated it into it's own"
  },
  {
    "path": "docs/CODE_OF_CONDUCT.md",
    "chars": 3965,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/CONTRIBUTING.md",
    "chars": 11100,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/FAQ.md",
    "chars": 22227,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/MAINTAINING.md",
    "chars": 4740,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/README.md",
    "chars": 3351,
    "preview": "# code-server\n\n[![\"GitHub Discussions\"](https://img.shields.io/badge/%20GitHub-%20Discussions-gray.svg?longCache=true&lo"
  },
  {
    "path": "docs/SECURITY.md",
    "chars": 1562,
    "preview": "# Security Policy\n\nCoder and the code-server team want to keep the code-server project secure and safe for end-users.\n\n#"
  },
  {
    "path": "docs/android.md",
    "chars": 968,
    "preview": "# Running code-server using UserLAnd\n\n1. Install UserLAnd from [Google Play](https://play.google.com/store/apps/details?"
  },
  {
    "path": "docs/coder.md",
    "chars": 1347,
    "preview": "# Coder\n\nTo install and run code-server in a Coder workspace, we suggest using the `install.sh`\nscript in your template "
  },
  {
    "path": "docs/collaboration.md",
    "chars": 2599,
    "preview": "# Collaboration\n\nWith third-party extensions, you can use code-server to collaborate with other developers in real time."
  },
  {
    "path": "docs/guide.md",
    "chars": 18965,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/helm.md",
    "chars": 6891,
    "preview": "# code-server Helm Chart\n\n[![Version: 1.0.0](https://img.shields.io/badge/Version-1.0.0-informational?style=flat-square)"
  },
  {
    "path": "docs/install.md",
    "chars": 11254,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/ios.md",
    "chars": 541,
    "preview": "# Using code-server on iOS with iSH\n\n1. Install iSH from the [App Store](https://apps.apple.com/us/app/ish-shell/id14369"
  },
  {
    "path": "docs/ipad.md",
    "chars": 8939,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/manifest.json",
    "chars": 3557,
    "preview": "{\n  \"versions\": [\"v4.8.0\"],\n  \"routes\": [\n    {\n      \"title\": \"Home\",\n      \"description\": \"Learn how to install and ru"
  },
  {
    "path": "docs/npm.md",
    "chars": 4776,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/requirements.md",
    "chars": 2595,
    "preview": "# Requirements\n\nYou'll need a machine on which you can run code-server. You can use a physical\nmachine you have, or you "
  },
  {
    "path": "docs/termux.md",
    "chars": 6566,
    "preview": "<!-- prettier-ignore-start -->\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DO"
  },
  {
    "path": "docs/triage.md",
    "chars": 1491,
    "preview": "# Triage\n\nTriaging code-server issues is done with the following issue filter:\n\n```text\nis:issue is:open no:project sort"
  },
  {
    "path": "docs/upgrade.md",
    "chars": 176,
    "preview": "# Upgrade\n\nTo upgrade code-server, install the new version over the old version. All user\ndata is in `~/.local/share/cod"
  },
  {
    "path": "eslint.config.mjs",
    "chars": 2136,
    "preview": "import { fixupConfigRules } from \"@eslint/compat\"\nimport globals from \"globals\"\nimport tsParser from \"@typescript-eslint"
  },
  {
    "path": "flake.nix",
    "chars": 1101,
    "preview": "{\n  description = \"code-server\";\n\n  inputs = {\n    nixpkgs.url = \"github:nixos/nixpkgs/nixos-unstable-small\";\n    flake-"
  },
  {
    "path": "install.sh",
    "chars": 15872,
    "preview": "#!/bin/sh\nset -eu\n\n# code-server's automatic install script.\n# See https://coder.com/docs/code-server/latest/install\n\nus"
  },
  {
    "path": "package.json",
    "chars": 4654,
    "preview": "{\n  \"name\": \"code-server\",\n  \"license\": \"MIT\",\n  \"version\": \"0.0.0\",\n  \"description\": \"Run VS Code on a remote server.\","
  },
  {
    "path": "patches/base-path.diff",
    "chars": 15529,
    "preview": "Add base path support\n\nSome users will host code-server behind a path-rewriting reverse proxy, for\nexample domain.tld/my"
  },
  {
    "path": "patches/cli-window-open.diff",
    "chars": 1364,
    "preview": "Make opening files/folders from the terminal only open in the current instance\n\nPreviously they would open in every code"
  },
  {
    "path": "patches/clipboard.diff",
    "chars": 6827,
    "preview": "Index: code-server/lib/vscode/src/vs/workbench/api/browser/mainThreadCLICommands.ts\n===================================="
  },
  {
    "path": "patches/disable-builtin-ext-update.diff",
    "chars": 949,
    "preview": "Prevent builtin extensions from being updated\n\nUpdating builtin extensions from the marketplace prevents us from patchin"
  },
  {
    "path": "patches/display-language.diff",
    "chars": 15890,
    "preview": "Add display language support\n\nVS Code web appears to implement language support by setting a cookie and\ndownloading lang"
  },
  {
    "path": "patches/external-file-actions.diff",
    "chars": 23056,
    "preview": "Add option to disable file downloads and uploads via cli\n\nThis patch adds support for a new CLI flag called `--disable-f"
  },
  {
    "path": "patches/fix-build.diff",
    "chars": 1804,
    "preview": "Fix protected field error\n\nThe mangler is reporting this error:\n\nWARN: 'setEditorVisible' from lib/vscode/src/vs/workben"
  },
  {
    "path": "patches/getting-started.diff",
    "chars": 13381,
    "preview": "Modify Help: Getting Started\n\nThis modifies some text on the Getting Started page and adds text about using\ncode-server "
  },
  {
    "path": "patches/insecure-notification.diff",
    "chars": 1885,
    "preview": "Add a notification when accessing code-server in an insecure context\n\nThis is done because otherwise when things like th"
  },
  {
    "path": "patches/integration.diff",
    "chars": 15462,
    "preview": "Prepare Code for integration with code-server\n\n1. We already have the arguments so allow passing them in.  There is also"
  },
  {
    "path": "patches/keepalive.diff",
    "chars": 710,
    "preview": "This can be removed after upgrading to Node >= 19 as keepAlive is defaulted to\ntrue after 19.\n\nIndex: code-server/lib/vs"
  },
  {
    "path": "patches/local-storage.diff",
    "chars": 4692,
    "preview": "Make storage local to the remote server\n\nThis makes user settings will be stored in the file system instead of in browse"
  },
  {
    "path": "patches/logout.diff",
    "chars": 4727,
    "preview": "Add a logout command and menu item\n\nThis will only show if you have authentication enabled.\n\nThis has e2e tests but are "
  },
  {
    "path": "patches/marketplace.diff",
    "chars": 5961,
    "preview": "Add Open VSX default and an env var for marketplace, fix old marketplace\n\nOur old marketplace only supports `serviceUrl`"
  },
  {
    "path": "patches/proposed-api.diff",
    "chars": 2233,
    "preview": "Unconditionally enable the proposed API\n\nTo test run an extension that uses the proposed API (i.e.\nhttps://github.com/mi"
  },
  {
    "path": "patches/proxy-uri.diff",
    "chars": 9037,
    "preview": "Add VSCODE_PROXY_URI environment variable\n\nThis can be used by extensions to open a port and access it through the proxy"
  },
  {
    "path": "patches/series",
    "chars": 472,
    "preview": "integration.diff\nbase-path.diff\nproposed-api.diff\nmarketplace.diff\nwebview.diff\ndisable-builtin-ext-update.diff\ninsecure"
  },
  {
    "path": "patches/service-worker.diff",
    "chars": 2693,
    "preview": "Add a service worker\n\nTo test try installing code-server as a PWA.\n\nIndex: code-server/lib/vscode/src/vs/base/common/pro"
  },
  {
    "path": "patches/signature-verification.diff",
    "chars": 2196,
    "preview": "Disable signature verification.\n\nExtension signature verification is now mandatory for all platforms and needs to be dis"
  },
  {
    "path": "patches/sourcemaps.diff",
    "chars": 2291,
    "preview": "Make sourcemaps self-hosted\n\nNormally source maps get removed as part of the build process so prevent that\nfrom happenin"
  },
  {
    "path": "patches/store-socket.diff",
    "chars": 4890,
    "preview": "Store the IPC socket with workspace metadata.\n\nThis lets us use it to open files inside code-server from outside of\ncode"
  },
  {
    "path": "patches/telemetry.diff",
    "chars": 7499,
    "preview": "Add support for telemetry endpoint\n\nTo test:\n1. Create a mock API using [RequestBin](https://requestbin.io/) or [Beecept"
  },
  {
    "path": "patches/trusted-domains.diff",
    "chars": 2184,
    "preview": "Allow configuring trusted domains via product.json or flag.\n\nIndex: code-server/lib/vscode/src/vs/server/node/serverEnvi"
  },
  {
    "path": "patches/unique-db.diff",
    "chars": 2187,
    "preview": "Prevent state collisions\n\nPreviously if you opened different workspaces that had the same filesystem path\n(for example i"
  },
  {
    "path": "patches/update-check.diff",
    "chars": 5422,
    "preview": "Add a notification that lets you know when an update is out\n\nThe easiest way to test this is probably to change the vers"
  },
  {
    "path": "patches/webview.diff",
    "chars": 6392,
    "preview": "Serve webviews from the same origin\n\nNormally webviews are served from vscode-webview.net but we would rather them be\nse"
  },
  {
    "path": "renovate.json",
    "chars": 552,
    "preview": "{\n  \"rangeStrategy\": \"replace\",\n  \"extends\": [\"config:base\"],\n  \"packageRules\": [\n    {\n      \"matchUpdateTypes\": [\"mino"
  },
  {
    "path": "src/browser/pages/error.css",
    "chars": 500,
    "preview": ".error-display {\n  box-sizing: border-box;\n  padding: 20px;\n  text-align: center;\n}\n\n.error-display > .header {\n  font-s"
  },
  {
    "path": "src/browser/pages/error.html",
    "chars": 1531,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta\n      name=\"viewport\"\n      content=\"wi"
  },
  {
    "path": "src/browser/pages/global.css",
    "chars": 1880,
    "preview": ":root {\n  color-scheme: light dark;\n}\n\nhtml,\nbody,\n#root {\n  height: 100%;\n  width: 100%;\n}\n\nbody {\n  background: rgb(24"
  },
  {
    "path": "src/browser/pages/login.css",
    "chars": 1097,
    "preview": "body {\n  min-height: 568px;\n  min-width: 320px;\n  overflow: auto;\n}\n\n.login-form {\n  display: flex;\n  flex-direction: co"
  },
  {
    "path": "src/browser/pages/login.html",
    "chars": 2591,
    "preview": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta\n      name=\"viewport\"\n      content=\"wi"
  },
  {
    "path": "src/browser/robots.txt",
    "chars": 26,
    "preview": "User-agent: *\nDisallow: /\n"
  },
  {
    "path": "src/browser/security.txt",
    "chars": 242,
    "preview": "Contact: mailto:security@coder.com\nAcknowledgments: https://coder.com/security/thanks\nPreferred-Languages: en-US\nCanonic"
  },
  {
    "path": "src/browser/serviceWorker.ts",
    "chars": 349,
    "preview": "self.addEventListener(\"install\", () => {\n  console.debug(\"[Service Worker] installed\")\n})\n\nself.addEventListener(\"activa"
  },
  {
    "path": "src/common/emitter.ts",
    "chars": 1292,
    "preview": "import { logger } from \"@coder/logger\"\n\n/**\n * Event emitter callback. Called with the emitted value and a promise that\n"
  },
  {
    "path": "src/common/http.ts",
    "chars": 700,
    "preview": "export enum HttpCode {\n  Ok = 200,\n  Redirect = 302,\n  NotFound = 404,\n  BadRequest = 400,\n  Unauthorized = 401,\n  Forbi"
  },
  {
    "path": "src/common/util.ts",
    "chars": 1228,
    "preview": "/**\n * Appends an 's' to the provided string if count is greater than one;\n * otherwise the string is returned\n */\nexpor"
  },
  {
    "path": "src/node/app.ts",
    "chars": 4280,
    "preview": "import { logger } from \"@coder/logger\"\nimport compression from \"compression\"\nimport express, { Express } from \"express\"\n"
  },
  {
    "path": "src/node/cli.ts",
    "chars": 27866,
    "preview": "import { field, Level, logger } from \"@coder/logger\"\nimport { promises as fs } from \"fs\"\nimport { load } from \"js-yaml\"\n"
  },
  {
    "path": "src/node/constants.ts",
    "chars": 1580,
    "preview": "import { logger } from \"@coder/logger\"\nimport type { JSONSchemaForNPMPackageJsonFiles } from \"@schemastore/package\"\nimpo"
  },
  {
    "path": "src/node/entry.ts",
    "chars": 2295,
    "preview": "import { logger } from \"@coder/logger\"\nimport { optionDescriptions, parse, readConfigFile, setDefaults, shouldOpenInExis"
  },
  {
    "path": "src/node/heart.ts",
    "chars": 2173,
    "preview": "import { logger } from \"@coder/logger\"\nimport { promises as fs } from \"fs\"\nimport { Emitter } from \"../common/emitter\"\n\n"
  },
  {
    "path": "src/node/http.ts",
    "chars": 13931,
    "preview": "import { field, logger } from \"@coder/logger\"\nimport * as express from \"express\"\nimport * as http from \"http\"\nimport * a"
  },
  {
    "path": "src/node/i18n/index.ts",
    "chars": 1755,
    "preview": "import { promises as fs } from \"fs\"\nimport i18next, { init } from \"i18next\"\nimport * as en from \"./locales/en.json\"\nimpo"
  },
  {
    "path": "src/node/i18n/locales/en.json",
    "chars": 508,
    "preview": "{\n  \"LOGIN_TITLE\": \"{{app}} login\",\n  \"LOGIN_BELOW\": \"Please log in below.\",\n  \"WELCOME\": \"Welcome to {{app}}\",\n  \"LOGIN"
  },
  {
    "path": "src/node/i18n/locales/ja.json",
    "chars": 463,
    "preview": "{\n  \"LOGIN_TITLE\": \"{{app}} ログイン\",\n  \"LOGIN_BELOW\": \"以下によりログインしてください。\",\n  \"WELCOME\": \"ようこそ {{app}} へ!\",\n  \"LOGIN_PASSWOR"
  },
  {
    "path": "src/node/i18n/locales/th.json",
    "chars": 521,
    "preview": "{\n  \"LOGIN_TITLE\": \"เข้าสู่ระบบ {{app}}\",\n  \"LOGIN_BELOW\": \"กรุณาเข้าสู่ระบบด้านล่าง\",\n  \"WELCOME\": \"ยินดีต้อนรับสู่ {{a"
  },
  {
    "path": "src/node/i18n/locales/ur.json",
    "chars": 525,
    "preview": "{\n  \"LOGIN_TITLE\": \"{{app}} لاگ ان کریں\",\n  \"LOGIN_BELOW\": \"براہ کرم نیچے لاگ ان کریں۔\",\n  \"WELCOME\": \"میں خوش آمدید {{a"
  },
  {
    "path": "src/node/i18n/locales/zh-cn.json",
    "chars": 383,
    "preview": "{\n  \"LOGIN_TITLE\": \"{{app}} 登录\",\n  \"LOGIN_BELOW\": \"请在下面登录。\",\n  \"WELCOME\": \"欢迎来到 {{app}}\",\n  \"LOGIN_PASSWORD\": \"查看配置文件中的密"
  },
  {
    "path": "src/node/main.ts",
    "chars": 8274,
    "preview": "import { field, logger } from \"@coder/logger\"\nimport http from \"http\"\nimport * as os from \"os\"\nimport * as path from \"pa"
  },
  {
    "path": "src/node/proxy.ts",
    "chars": 1164,
    "preview": "import proxyServer from \"http-proxy\"\nimport { HttpCode } from \"../common/http\"\n\nexport const proxy = proxyServer.createP"
  },
  {
    "path": "src/node/routes/domainProxy.ts",
    "chars": 3597,
    "preview": "import { Request, Router } from \"express\"\nimport { HttpCode, HttpError } from \"../../common/http\"\nimport { getHost, ensu"
  },
  {
    "path": "src/node/routes/errors.ts",
    "chars": 2960,
    "preview": "import { logger } from \"@coder/logger\"\nimport express from \"express\"\nimport { promises as fs } from \"fs\"\nimport path fro"
  },
  {
    "path": "src/node/routes/health.ts",
    "chars": 668,
    "preview": "import { Router } from \"express\"\nimport { wss, Router as WsRouter } from \"../wsRouter\"\n\nexport const router = Router()\n\n"
  },
  {
    "path": "src/node/routes/index.ts",
    "chars": 6627,
    "preview": "import { logger } from \"@coder/logger\"\nimport cookieParser from \"cookie-parser\"\nimport * as express from \"express\"\nimpor"
  },
  {
    "path": "src/node/routes/login.ts",
    "chars": 4549,
    "preview": "import { Router, Request } from \"express\"\nimport { promises as fs } from \"fs\"\nimport { RateLimiter as Limiter } from \"li"
  },
  {
    "path": "src/node/routes/logout.ts",
    "chars": 523,
    "preview": "import { Router } from \"express\"\nimport { getCookieOptions, redirect } from \"../http\"\nimport { sanitizeString } from \".."
  },
  {
    "path": "src/node/routes/pathProxy.ts",
    "chars": 2253,
    "preview": "import { Request, Response } from \"express\"\nimport * as path from \"path\"\nimport { HttpCode, HttpError } from \"../../comm"
  },
  {
    "path": "src/node/routes/update.ts",
    "chars": 439,
    "preview": "import { Router } from \"express\"\nimport { version } from \"../constants\"\nimport { ensureAuthenticated } from \"../http\"\n\ne"
  },
  {
    "path": "src/node/routes/vscode.ts",
    "chars": 8826,
    "preview": "import { logger } from \"@coder/logger\"\nimport * as crypto from \"crypto\"\nimport * as express from \"express\"\nimport { prom"
  },
  {
    "path": "src/node/settings.ts",
    "chars": 1426,
    "preview": "import { logger } from \"@coder/logger\"\nimport type { ParsedQs } from \"qs\"\nimport { promises as fs } from \"fs\"\n\nexport ty"
  },
  {
    "path": "src/node/socket.ts",
    "chars": 3420,
    "preview": "import { promises as fs } from \"fs\"\nimport * as net from \"net\"\nimport * as path from \"path\"\nimport * as stream from \"str"
  },
  {
    "path": "src/node/update.ts",
    "chars": 4279,
    "preview": "import { field, logger } from \"@coder/logger\"\nimport * as http from \"http\"\nimport * as https from \"https\"\nimport { Proxy"
  },
  {
    "path": "src/node/util.ts",
    "chars": 14885,
    "preview": "import * as argon2 from \"argon2\"\nimport * as cp from \"child_process\"\nimport * as crypto from \"crypto\"\nimport envPaths fr"
  },
  {
    "path": "src/node/vscodeSocket.ts",
    "chars": 5810,
    "preview": "import { logger } from \"@coder/logger\"\nimport express from \"express\"\nimport * as http from \"http\"\nimport * as path from "
  },
  {
    "path": "src/node/wrapper.ts",
    "chars": 11241,
    "preview": "import { field, Logger, logger } from \"@coder/logger\"\nimport * as cp from \"child_process\"\nimport * as path from \"path\"\ni"
  },
  {
    "path": "src/node/wsRouter.ts",
    "chars": 1847,
    "preview": "import * as express from \"express\"\nimport * as expressCore from \"express-serve-static-core\"\nimport * as http from \"http\""
  },
  {
    "path": "test/e2e/baseFixture.ts",
    "chars": 2072,
    "preview": "import { test as base } from \"@playwright/test\"\nimport { CodeServer, CodeServerPage } from \"./models/CodeServer\"\n\n/**\n *"
  },
  {
    "path": "test/e2e/codeServer.test.ts",
    "chars": 1765,
    "preview": "import { promises as fs } from \"fs\"\nimport * as path from \"path\"\nimport { getMaybeProxiedCodeServer } from \"../utils/hel"
  },
  {
    "path": "test/e2e/downloads.test.ts",
    "chars": 4449,
    "preview": "import { promises as fs } from \"fs\"\nimport * as path from \"path\"\nimport { clean } from \"../utils/helpers\"\nimport { descr"
  },
  {
    "path": "test/e2e/extensions/test-extension/.gitignore",
    "chars": 14,
    "preview": "/extension.js\n"
  },
  {
    "path": "test/e2e/extensions/test-extension/extension.ts",
    "chars": 1076,
    "preview": "import * as vscode from \"vscode\"\n\nexport function activate(context: vscode.ExtensionContext) {\n  vscode.window.showInfor"
  },
  {
    "path": "test/e2e/extensions/test-extension/package.json",
    "chars": 721,
    "preview": "{\n  \"name\": \"code-server-extension\",\n  \"description\": \"code-server test extension\",\n  \"version\": \"0.0.1\",\n  \"publisher\":"
  },
  {
    "path": "test/e2e/extensions/test-extension/tsconfig.json",
    "chars": 230,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"es2020\",\n    \"module\": \"commonjs\",\n    \"outDir\": \".\",\n    \"strict\": true,\n    \"b"
  },
  {
    "path": "test/e2e/extensions.test.ts",
    "chars": 1291,
    "preview": "import { test as base } from \"@playwright/test\"\nimport * as path from \"path\"\nimport { getMaybeProxiedCodeServer } from \""
  },
  {
    "path": "test/e2e/github.test.ts",
    "chars": 1928,
    "preview": "import { test as base } from \"@playwright/test\"\nimport { describe, expect, test } from \"./baseFixture\"\n\nif (process.env."
  },
  {
    "path": "test/e2e/login.test.ts",
    "chars": 2699,
    "preview": "import { PASSWORD } from \"../utils/constants\"\nimport { describe, test, expect } from \"./baseFixture\"\n\ndescribe(\"login\", "
  },
  {
    "path": "test/e2e/logout.test.ts",
    "chars": 658,
    "preview": "// NOTE@jsjoeio commenting out until we can figure out what's wrong\n// import { describe, test, expect } from \"./baseFix"
  },
  {
    "path": "test/e2e/models/CodeServer.ts",
    "chars": 18745,
    "preview": "import { field, Logger, logger } from \"@coder/logger\"\nimport * as cp from \"child_process\"\nimport { promises as fs } from"
  },
  {
    "path": "test/e2e/openHelpAbout.test.ts",
    "chars": 650,
    "preview": "import { version } from \"../../src/node/constants\"\nimport { describe, test, expect } from \"./baseFixture\"\n\ndescribe(\"Ope"
  },
  {
    "path": "test/e2e/routes.test.ts",
    "chars": 4793,
    "preview": "import { clean, getMaybeProxiedPathname } from \"../utils/helpers\"\nimport { describe, test, expect } from \"./baseFixture\""
  },
  {
    "path": "test/e2e/terminal.test.ts",
    "chars": 1953,
    "preview": "import * as cp from \"child_process\"\nimport { promises as fs } from \"fs\"\nimport * as path from \"path\"\nimport util from \"u"
  },
  {
    "path": "test/e2e/uploads.test.ts",
    "chars": 2033,
    "preview": "import { promises as fs } from \"fs\"\nimport * as path from \"path\"\nimport { clean } from \"../utils/helpers\"\nimport { descr"
  },
  {
    "path": "test/e2e/webview.test.ts",
    "chars": 953,
    "preview": "import { promises as fs } from \"fs\"\nimport * as path from \"path\"\nimport { describe, test, expect } from \"./baseFixture\"\n"
  },
  {
    "path": "test/integration/help.test.ts",
    "chars": 486,
    "preview": "import { runCodeServerCommand } from \"../utils/runCodeServerCommand\"\n\n// NOTE@jsjoeio\n// We have this test to ensure tha"
  },
  {
    "path": "test/integration/installExtension.test.ts",
    "chars": 702,
    "preview": "import { clean, tmpdir } from \"../utils/helpers\"\nimport { runCodeServerCommand } from \"../utils/runCodeServerCommand\"\n\nd"
  },
  {
    "path": "test/package.json",
    "chars": 776,
    "preview": "{\n  \"license\": \"MIT\",\n  \"#\": \"We must put jest in a sub-directory otherwise VS Code somehow picks up the types and gener"
  },
  {
    "path": "test/playwright.config.ts",
    "chars": 1476,
    "preview": "import { PlaywrightTestConfig } from \"@playwright/test\"\n\nimport path from \"path\"\n\n// The default configuration runs all "
  },
  {
    "path": "test/scripts/build-lib.bats",
    "chars": 495,
    "preview": "#!/usr/bin/env bats\n\nSCRIPT_NAME=\"build-lib.sh\"\nSCRIPT=\"$BATS_TEST_DIRNAME/../../ci/build/$SCRIPT_NAME\"\n\nsource \"$SCRIPT"
  },
  {
    "path": "test/scripts/install.bats",
    "chars": 5096,
    "preview": "#!/usr/bin/env bats\n\nSCRIPT_NAME=\"install.sh\"\nSCRIPT=\"$BATS_TEST_DIRNAME/../../$SCRIPT_NAME\"\n\n# Override version so it d"
  },
  {
    "path": "test/scripts/steps-lib.bats",
    "chars": 1056,
    "preview": "#!/usr/bin/env bats\n\nSCRIPT_NAME=\"steps-lib.sh\"\nSCRIPT=\"$BATS_TEST_DIRNAME/../../ci/steps/$SCRIPT_NAME\"\n\nsource \"$SCRIPT"
  },
  {
    "path": "test/tsconfig.json",
    "chars": 64,
    "preview": "{\n  \"extends\": \"../tsconfig.json\",\n  \"include\": [\"./**/*.ts\"]\n}\n"
  },
  {
    "path": "test/unit/common/emitter.test.ts",
    "chars": 2550,
    "preview": "import { logger } from \"@coder/logger\"\nimport { Emitter } from \"../../../src/common/emitter\"\nimport { mockLogger } from "
  },
  {
    "path": "test/unit/common/http.test.ts",
    "chars": 1167,
    "preview": "import { HttpCode, HttpError } from \"../../../src/common/http\"\n\ndescribe(\"http\", () => {\n  describe(\"HttpCode\", () => {\n"
  }
]

// ... and 32 more files (download for full content)

About this extraction

This page contains the full source code of the coder/code-server GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 232 files (813.5 KB), approximately 216.1k tokens, and a symbol index with 231 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!