diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 00000000..5ac3a9e7
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,4 @@
+{
+ "image": "mcr.microsoft.com/devcontainers/universal:debian",
+ "updateContentCommand": "pip install bikeshed && bikeshed update"
+}
diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml
new file mode 100644
index 00000000..2c71eba0
--- /dev/null
+++ b/.github/workflows/deploy-pages.yml
@@ -0,0 +1,33 @@
+name: deploy-pages
+on:
+ push:
+ branches: "main"
+ paths:
+ - "*.schema.json"
+ - index.bs
+ - .github/workflows/deploy-pages.yml
+ workflow_dispatch:
+concurrency:
+ group: ${{ github.workflow }}
+ cancel-in-progress: true
+jobs:
+ deploy-github-pages:
+ permissions:
+ id-token: write
+ pages: write
+ deployments: write
+ environment:
+ name: github-pages
+ url: ${{ steps.deploy-pages.outputs.page_url }}
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - run: pip install bikeshed && bikeshed update
+ - id: configure-pages
+ uses: actions/configure-pages@v3
+ - run: bikeshed
+ - uses: actions/upload-pages-artifact@v2
+ with:
+ path: .
+ - id: deploy-pages
+ uses: actions/deploy-pages@v2
diff --git a/.gitignore b/.gitignore
index dfcfd56f..406a8a86 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,350 +1,2 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
-
-# User-specific files
-*.rsuser
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Mono auto generated files
-mono_crash.*
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-[Aa][Rr][Mm]/
-[Aa][Rr][Mm]64/
-bld/
-[Bb]in/
-[Oo]bj/
-[Ll]og/
-[Ll]ogs/
-
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUnit
-*.VisualState.xml
-TestResult.xml
-nunit-*.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# NuGet Symbol Packages
-*.snupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-*.appxbundle
-*.appxupload
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!?*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-*- [Bb]ackup.rdl
-*- [Bb]ackup ([0-9]).rdl
-*- [Bb]ackup ([0-9][0-9]).rdl
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# CodeRush personal settings
-.cr/personal
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-
-# Local History for Visual Studio
-.localhistory/
-
-# BeatPulse healthcheck temp database
-healthchecksdb
-
-# Backup folder for Package Reference Convert tool in Visual Studio 2017
-MigrationBackup/
-
-# Ionide (cross platform F# VS Code tools) working folder
-.ionide/
+# Bikeshed build artifact
+index.html
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 00000000..152a9b62
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,3 @@
+{
+ "recommendations": ["kainino.bikeshed"]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 00000000..5b01c983
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,7 @@
+{
+ "editor.wordWrap": "bounded",
+ "editor.wordWrapColumn": 120,
+ "editor.wrappingIndent": "indent",
+ "editor.wrappingStrategy": "advanced",
+ "editor.minimap.enabled": true
+}
diff --git a/CODEOWNERS b/CODEOWNERS
deleted file mode 100644
index f9ed0b93..00000000
--- a/CODEOWNERS
+++ /dev/null
@@ -1 +0,0 @@
-* @devcontainers/maintainers
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
deleted file mode 100644
index f9ba8cf6..00000000
--- a/CODE_OF_CONDUCT.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Microsoft Open Source Code of Conduct
-
-This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
-
-Resources:
-
-- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
-- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
-- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
diff --git a/contributing.md b/CONTRIBUTING.md
similarity index 56%
rename from contributing.md
rename to CONTRIBUTING.md
index 503a186e..16c2f48e 100644
--- a/contributing.md
+++ b/CONTRIBUTING.md
@@ -1,18 +1,19 @@
# How to Contribute to the Dev Container Specification
-We're excited for your contributions to the dev container specification! This document outlines how you can get involved.
+We're excited for your contributions to the dev container specification! This document outlines how you can get involved.
## Contribution approaches
If you'd like to contribute a change or addition to the spec, you may follow the guidance below:
+
- Propose the change via an [issue](https://github.com/microsoft/dev-container-spec/issues) in this repository. Try to get early feedback before spending too much effort formalizing it.
- More formally document the proposed change in terms of properties and their semantics. Look to format your proposal like our [devcontainer.json reference](https://aka.ms/devcontainer.json), which is a JSON with Comments (jsonc) format.
Here is a sample:
-| Property | Type | Description |
-|----------|------|-------------|
-| `image` | string | **Required** when [using an image](/docs/remote/create-dev-container.md#using-an-image-or-dockerfile). The name of an image in a container registry ([DockerHub](https://hub.docker.com), [GitHub Container Registry](https://docs.github.com/packages/guides/about-github-container-registry), [Azure Container Registry](https://azure.microsoft.com/services/container-registry/)) that VS Code and other `devcontainer.json` supporting services / tools should use to create the dev container. |
+| Property | Type | Description |
+| -------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `image` | string | **Required** when [using an image](/docs/remote/create-dev-container.md#using-an-image-or-dockerfile). The name of an image in a container registry ([DockerHub](https://hub.docker.com), [GitHub Container Registry](https://docs.github.com/packages/guides/about-github-container-registry), [Azure Container Registry](https://azure.microsoft.com/services/container-registry/)) that VS Code and other `devcontainer.json` supporting services / tools should use to create the dev container. |
- PRs to the [schema](https://github.com/devcontainers/spec/blob/main/schemas/devContainer.base.schema.json), i.e code or shell scripts demonstrating approaches for implementation.
@@ -22,22 +23,25 @@ Once there is discussion on your proposal, please also open and link a PR to upd
Tool-specific properties are contained in namespaces in the `"customizations"` property. For instance, VS Code specific properties are formatted as:
-```bash
-// Configure tool-specific properties.
-"customizations": {
- // Configure properties specific to VS Code.
- "vscode": {
- // Set *default* container specific settings.json values on container create.
- "settings": {},
-
- // Additional VS Code specific properties...
- }
-},
+```jsonc
+{
+ // Configure tool-specific properties.
+ "customizations": {
+ // Configure properties specific to VS Code.
+ "vscode": {
+ // Set *default* container specific settings.json values on container create.
+ "settings": {}
+
+ // Additional VS Code specific properties...
+ }
+ }
+}
```
You may propose adding a new namespace for a specific tool, and any properties specific to that tool.
### GitHub Discussions
+
If you'd like to discuss the spec, such as asking questions, providing feedback, or engaging on how your team may use or contribute to dev containers, please check out the [GitHub Discussions](https://github.com/devcontainers/spec/discussions) in this repo. This is a great opportunity to connect with the community and maintainers of this project, without the requirement of contributing a change to the actual spec (which we see more in issues and PRs).
## Review process
diff --git a/LICENSE-CODE b/LICENSE-CODE
deleted file mode 100644
index 9e841e7a..00000000
--- a/LICENSE-CODE
+++ /dev/null
@@ -1,21 +0,0 @@
- MIT License
-
- Copyright (c) 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
diff --git a/README.md b/README.md
index da3bc81a..a64d0bf5 100644
--- a/README.md
+++ b/README.md
@@ -1,42 +1,56 @@
-# Development Containers
+
You're probably looking for devcontainers.org/spec 😉
-This repository is for the Development Container Specification.
+# Development Containers specification
-A development container allows you to use a container as a full-featured development environment. It can be used to run an application, to separate tools, libraries, or runtimes needed for working with a codebase, and to aid in continuous integration and testing.
+💻 Formal specification for Development Containers
-The Development Containers Specification seeks to find ways to enrich existing formats with common development specific settings, tools, and configuration while still providing a simplified, un-orchestrated single container option – so that they can be used as coding environments or for continuous integration and testing.
+
+
+
-
+## Usage
-The first format in the specification, `devcontainer.json`, was born out of necessity. It is a structured JSON with Comments (jsonc) metadata format that tools can use to store any needed configuration required to develop inside of local or cloud-based containerized coding.
+To use the JSON schema files:
-We envision that this same structured data can be embedded in images and other formats – all while retaining a common object model for consistent processing. For example, some of this same metadata can be added to a `devcontainer.metadata` image label to tie settings directly to a container image.
+```jsonc
+{
+ "$schema": "https://devcontainers.org/spec/devcontainer.schema.json"
+}
+```
-Beyond repeatable setup, these same development containers provide consistency to avoid environment specific problems across developers and centralized build and test automation services. You can use the [open-source CLI reference implementation](https://github.com/devcontainers/cli) either directly or integrated into product experiences to use the structured metadata to deliver these benefits. It currently supports integrating with Docker Compose and a simplified, un-orchestrated single container option – so that they can be used as coding environments or for continuous integration and testing.
+## Development
-A GitHub Action and an Azure DevOps Task are available in [devcontainers/ci](https://github.com/devcontainers/ci) for running a repository's dev container in continuous integration (CI) builds. This allows you to reuse the same setup that you are using for local development to also build and test your code in CI.
+To get started, make sure you have [Bikeshed] installed, then run these commands
+in **two separate terminals** (so that they're running simultaneously):
-### Spec content
+```sh
+bikeshed watch
+python -m http.server
+```
-You may review the specification in the [specs folder](https://github.com/devcontainers/spec/tree/main/docs/specs) of this repo.
+If you're on Linux you can use the `&` operator
-You may also review proposed references in the [proposals folder](https://github.com/devcontainers/spec/tree/main/proposals).
+In VS Code you can click the [|] button in the terminal to split it
+into two.
-Images used in this repo will be contained in the [images folder](/images). The icon for the [devcontainers org](https://github.com/devcontainers) is from the [Fluent icon library](https://github.com/microsoft/fluentui-system-icons/blob/master/assets/Cube/SVG/ic_fluent_cube_32_filled.svg).
+ℹ Bikeshed supports all of CommonMark, but not GFM. For instance, [tables must be
+HTML `` elements] instead of `|`-delimited Markdown tables. But don't let
+that fool you! It's auto-linking features _vastly_ surpass plain Markdown. Make
+sure you use `[=hello=]` to autolink to `hello`!
-## Contributing and Feedback
+If you want to add a big text minimap marker, do this:
-If you are interested in contributing, please check out the [How to Contribute](contributing.md) document or [start a discussion](https://github.com/devcontainers/spec/discussions).
+```html
+
-Please report issues in the following repositories:
+# My new section
+```
-- Reference implementation Features and templates: [devcontainers/features](https://github.com/devcontainers/features), [devcontainers/templates](https://github.com/devcontainers/templates)
-- CLI reference implementation and non-spec related feature requests: [devcontainers/cli](https://github.com/devcontainers/cli)
-- GitHub Action and Azure DevOps Task: [devcontainers/ci](https://github.com/devcontainers/ci)
+```sh
+bikeshed source --big-text
+```
-# License
-
-License for this repository:
-
-Copyright © Microsoft Corporation All rights reserved.
-Creative Commons Attribution 4.0 License (International): https://creativecommons.org/licenses/by/4.0/legalcode
+
+[Bikeshed]: https://speced.github.io/bikeshed/
+[tables must be HTML `` elements]: https://github.com/speced/bikeshed/issues/1128#issuecomment-388907059
+
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index f7b89984..00000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-## Security
-
-Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
-
-If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below.
-
-## Reporting Security Issues
-
-**Please do not report security vulnerabilities through public GitHub issues.**
-
-Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
-
-If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
-
-You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
-
-Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
-
- * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
- * Full paths of source file(s) related to the manifestation of the issue
- * The location of the affected source code (tag/branch/commit or direct URL)
- * Any special configuration required to reproduce the issue
- * Step-by-step instructions to reproduce the issue
- * Proof-of-concept or exploit code (if possible)
- * Impact of the issue, including how an attacker might exploit the issue
-
-This information will help us triage your report more quickly.
-
-If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
-
-## Preferred Languages
-
-We prefer all communications to be in English.
-
-## Policy
-
-Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
-
-
\ No newline at end of file
diff --git a/devcontainer-base.schema.json b/devcontainer-base.schema.json
new file mode 100644
index 00000000..47984c00
--- /dev/null
+++ b/devcontainer-base.schema.json
@@ -0,0 +1,639 @@
+{
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
+ "description": "Defines a dev container",
+ "allowComments": true,
+ "allowTrailingCommas": false,
+ "definitions": {
+ "devContainerCommon": {
+ "type": "object",
+ "properties": {
+ "$schema": {
+ "type": "string",
+ "format": "uri",
+ "description": "The JSON schema of the `devcontainer.json` file."
+ },
+ "name": {
+ "type": "string",
+ "description": "A name for the dev container which can be displayed to the user."
+ },
+ "features": {
+ "type": "object",
+ "description": "Features to add to the dev container.",
+ "properties": {
+ "fish": {
+ "deprecated": true,
+ "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements."
+ },
+ "maven": {
+ "deprecated": true,
+ "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements. E.g., `ghcr.io/devcontainers/features/java` has an option to install Maven."
+ },
+ "gradle": {
+ "deprecated": true,
+ "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements. E.g., `ghcr.io/devcontainers/features/java` has an option to install Gradle."
+ },
+ "homebrew": {
+ "deprecated": true,
+ "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements."
+ },
+ "jupyterlab": {
+ "deprecated": true,
+ "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements. E.g., `ghcr.io/devcontainers/features/python` has an option to install JupyterLab."
+ }
+ },
+ "additionalProperties": true
+ },
+ "overrideFeatureInstallOrder": {
+ "type": "array",
+ "description": "Array consisting of the Feature id (without the semantic version) of Features in the order the user wants them to be installed.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "forwardPorts": {
+ "type": "array",
+ "description": "Ports that are forwarded from the container to the local machine. Can be an integer port number, or a string of the format \"host:port_number\".",
+ "items": {
+ "oneOf": [
+ {
+ "type": "integer",
+ "maximum": 65535,
+ "minimum": 0
+ },
+ {
+ "type": "string",
+ "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
+ }
+ ]
+ }
+ },
+ "portsAttributes": {
+ "type": "object",
+ "patternProperties": {
+ "(^\\d+(-\\d+)?$)|(.+)": {
+ "type": "object",
+ "description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
+ "properties": {
+ "onAutoForward": {
+ "type": "string",
+ "enum": [
+ "notify",
+ "openBrowser",
+ "openBrowserOnce",
+ "openPreview",
+ "silent",
+ "ignore"
+ ],
+ "enumDescriptions": [
+ "Shows a notification when a port is automatically forwarded.",
+ "Opens the browser when the port is automatically forwarded. Depending on your settings, this could open an embedded browser.",
+ "Opens the browser when the port is automatically forwarded, but only the first time the port is forward during a session. Depending on your settings, this could open an embedded browser.",
+ "Opens a preview in the same window when the port is automatically forwarded.",
+ "Shows no notification and takes no action when this port is automatically forwarded.",
+ "This port will not be automatically forwarded."
+ ],
+ "description": "Defines the action that occurs when the port is discovered for automatic forwarding",
+ "default": "notify"
+ },
+ "elevateIfNeeded": {
+ "type": "boolean",
+ "description": "Automatically prompt for elevation (if needed) when this port is forwarded. Elevate is required if the local port is a privileged port.",
+ "default": false
+ },
+ "label": {
+ "type": "string",
+ "description": "Label that will be shown in the UI for this port.",
+ "default": "Application"
+ },
+ "requireLocalPort": {
+ "type": "boolean",
+ "markdownDescription": "When true, a modal dialog will show if the chosen local port isn't used for forwarding.",
+ "default": false
+ },
+ "protocol": {
+ "type": "string",
+ "enum": ["http", "https"],
+ "description": "The protocol to use when forwarding this port."
+ }
+ },
+ "default": {
+ "label": "Application",
+ "onAutoForward": "notify"
+ }
+ }
+ },
+ "markdownDescription": "Set default properties that are applied when a specific port number is forwarded. For example:\n\n```\n\"3000\": {\n \"label\": \"Application\"\n},\n\"40000-55000\": {\n \"onAutoForward\": \"ignore\"\n},\n\".+\\\\/server.js\": {\n \"onAutoForward\": \"openPreview\"\n}\n```",
+ "defaultSnippets": [
+ {
+ "body": {
+ "${1:3000}": {
+ "label": "${2:Application}",
+ "onAutoForward": "notify"
+ }
+ }
+ }
+ ],
+ "additionalProperties": false
+ },
+ "otherPortsAttributes": {
+ "type": "object",
+ "properties": {
+ "onAutoForward": {
+ "type": "string",
+ "enum": [
+ "notify",
+ "openBrowser",
+ "openPreview",
+ "silent",
+ "ignore"
+ ],
+ "enumDescriptions": [
+ "Shows a notification when a port is automatically forwarded.",
+ "Opens the browser when the port is automatically forwarded. Depending on your settings, this could open an embedded browser.",
+ "Opens a preview in the same window when the port is automatically forwarded.",
+ "Shows no notification and takes no action when this port is automatically forwarded.",
+ "This port will not be automatically forwarded."
+ ],
+ "description": "Defines the action that occurs when the port is discovered for automatic forwarding",
+ "default": "notify"
+ },
+ "elevateIfNeeded": {
+ "type": "boolean",
+ "description": "Automatically prompt for elevation (if needed) when this port is forwarded. Elevate is required if the local port is a privileged port.",
+ "default": false
+ },
+ "label": {
+ "type": "string",
+ "description": "Label that will be shown in the UI for this port.",
+ "default": "Application"
+ },
+ "requireLocalPort": {
+ "type": "boolean",
+ "markdownDescription": "When true, a modal dialog will show if the chosen local port isn't used for forwarding.",
+ "default": false
+ },
+ "protocol": {
+ "type": "string",
+ "enum": ["http", "https"],
+ "description": "The protocol to use when forwarding this port."
+ }
+ },
+ "defaultSnippets": [
+ {
+ "body": {
+ "onAutoForward": "ignore"
+ }
+ }
+ ],
+ "markdownDescription": "Set default properties that are applied to all ports that don't get properties from the setting `remote.portsAttributes`. For example:\n\n```\n{\n \"onAutoForward\": \"ignore\"\n}\n```",
+ "additionalProperties": false
+ },
+ "updateRemoteUserUID": {
+ "type": "boolean",
+ "description": "Controls whether on Linux the container's user should be updated with the local user's UID and GID. On by default when opening from a local folder."
+ },
+ "containerEnv": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "string"
+ },
+ "description": "Container environment variables."
+ },
+ "containerUser": {
+ "type": "string",
+ "description": "The user the container will be started with. The default is the user on the Docker image."
+ },
+ "mounts": {
+ "type": "array",
+ "description": "Mount points to set up when creating the container. See Docker's documentation for the --mount option for the supported syntax.",
+ "items": {
+ "anyOf": [
+ {
+ "$ref": "#/definitions/Mount"
+ },
+ {
+ "type": "string"
+ }
+ ]
+ }
+ },
+ "init": {
+ "type": "boolean",
+ "description": "Passes the --init flag when creating the dev container."
+ },
+ "privileged": {
+ "type": "boolean",
+ "description": "Passes the --privileged flag when creating the dev container."
+ },
+ "capAdd": {
+ "type": "array",
+ "description": "Passes docker capabilities to include when creating the dev container.",
+ "examples": ["SYS_PTRACE"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "securityOpt": {
+ "type": "array",
+ "description": "Passes docker security options to include when creating the dev container.",
+ "examples": ["seccomp=unconfined"],
+ "items": {
+ "type": "string"
+ }
+ },
+ "remoteEnv": {
+ "type": "object",
+ "additionalProperties": {
+ "type": ["string", "null"]
+ },
+ "description": "Remote environment variables to set for processes spawned in the container including lifecycle scripts and any remote editor/IDE server process."
+ },
+ "remoteUser": {
+ "type": "string",
+ "description": "The username to use for spawning processes in the container including lifecycle scripts and any remote editor/IDE server process. The default is the same user as the container."
+ },
+ "initializeCommand": {
+ "type": ["string", "array", "object"],
+ "description": "A command to run locally (i.e Your host machine, cloud VM) before anything else. This command is run before \"onCreateCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
+ "items": {
+ "type": "string"
+ },
+ "additionalProperties": {
+ "type": ["string", "array"],
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "onCreateCommand": {
+ "type": ["string", "array", "object"],
+ "description": "A command to run when creating the container. This command is run after \"initializeCommand\" and before \"updateContentCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
+ "items": {
+ "type": "string"
+ },
+ "additionalProperties": {
+ "type": ["string", "array"],
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "updateContentCommand": {
+ "type": ["string", "array", "object"],
+ "description": "A command to run when creating the container and rerun when the workspace content was updated while creating the container. This command is run after \"onCreateCommand\" and before \"postCreateCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
+ "items": {
+ "type": "string"
+ },
+ "additionalProperties": {
+ "type": ["string", "array"],
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "postCreateCommand": {
+ "type": ["string", "array", "object"],
+ "description": "A command to run after creating the container. This command is run after \"updateContentCommand\" and before \"postStartCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
+ "items": {
+ "type": "string"
+ },
+ "additionalProperties": {
+ "type": ["string", "array"],
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "postStartCommand": {
+ "type": ["string", "array", "object"],
+ "description": "A command to run after starting the container. This command is run after \"postCreateCommand\" and before \"postAttachCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
+ "items": {
+ "type": "string"
+ },
+ "additionalProperties": {
+ "type": ["string", "array"],
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "postAttachCommand": {
+ "type": ["string", "array", "object"],
+ "description": "A command to run when attaching to the container. This command is run after \"postStartCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
+ "items": {
+ "type": "string"
+ },
+ "additionalProperties": {
+ "type": ["string", "array"],
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "waitFor": {
+ "type": "string",
+ "enum": [
+ "initializeCommand",
+ "onCreateCommand",
+ "updateContentCommand",
+ "postCreateCommand",
+ "postStartCommand"
+ ],
+ "description": "The user command to wait for before continuing execution in the background while the UI is starting up. The default is \"updateContentCommand\"."
+ },
+ "userEnvProbe": {
+ "type": "string",
+ "enum": [
+ "none",
+ "loginShell",
+ "loginInteractiveShell",
+ "interactiveShell"
+ ],
+ "description": "User environment probe to run. The default is \"loginInteractiveShell\"."
+ },
+ "hostRequirements": {
+ "type": "object",
+ "description": "Host hardware requirements.",
+ "properties": {
+ "cpus": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Number of required CPUs."
+ },
+ "memory": {
+ "type": "string",
+ "pattern": "^\\d+([tgmk]b)?$",
+ "description": "Amount of required RAM in bytes. Supports units tb, gb, mb and kb."
+ },
+ "storage": {
+ "type": "string",
+ "pattern": "^\\d+([tgmk]b)?$",
+ "description": "Amount of required disk space in bytes. Supports units tb, gb, mb and kb."
+ },
+ "gpu": {
+ "oneOf": [
+ {
+ "type": ["boolean", "string"],
+ "enum": [true, false, "optional"],
+ "description": "Indicates whether a GPU is required. The string \"optional\" indicates that a GPU is optional. An object value can be used to configure more detailed requirements."
+ },
+ {
+ "type": "object",
+ "properties": {
+ "cores": {
+ "type": "integer",
+ "minimum": 1,
+ "description": "Number of required cores."
+ },
+ "memory": {
+ "type": "string",
+ "pattern": "^\\d+([tgmk]b)?$",
+ "description": "Amount of required RAM in bytes. Supports units tb, gb, mb and kb."
+ }
+ },
+ "description": "Indicates whether a GPU is required. The string \"optional\" indicates that a GPU is optional. An object value can be used to configure more detailed requirements.",
+ "additionalProperties": false
+ }
+ ]
+ }
+ },
+ "unevaluatedProperties": false
+ },
+ "customizations": {
+ "type": "object",
+ "description": "Tool-specific configuration. Each tool should use a JSON object subproperty with a unique name to group its customizations."
+ },
+ "additionalProperties": {
+ "type": "object",
+ "additionalProperties": true
+ }
+ }
+ },
+ "nonComposeBase": {
+ "type": "object",
+ "properties": {
+ "appPort": {
+ "type": ["integer", "string", "array"],
+ "description": "Application ports that are exposed by the container. This can be a single port or an array of ports. Each port can be a number or a string. A number is mapped to the same port on the host. A string is passed to Docker unchanged and can be used to map ports differently, e.g. \"8000:8010\".",
+ "items": {
+ "type": ["integer", "string"]
+ }
+ },
+ "runArgs": {
+ "type": "array",
+ "description": "The arguments required when starting in the container.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "shutdownAction": {
+ "type": "string",
+ "enum": ["none", "stopContainer"],
+ "description": "Action to take when the user disconnects from the container in their editor. The default is to stop the container."
+ },
+ "overrideCommand": {
+ "type": "boolean",
+ "description": "Whether to overwrite the command specified in the image. The default is true."
+ },
+ "workspaceFolder": {
+ "type": "string",
+ "description": "The path of the workspace folder inside the container."
+ },
+ "workspaceMount": {
+ "type": "string",
+ "description": "The --mount parameter for docker run. The default is to mount the project folder at /workspaces/$project."
+ }
+ }
+ },
+ "dockerfileContainer": {
+ "oneOf": [
+ {
+ "type": "object",
+ "properties": {
+ "build": {
+ "type": "object",
+ "description": "Docker build-related options.",
+ "allOf": [
+ {
+ "type": "object",
+ "properties": {
+ "dockerfile": {
+ "type": "string",
+ "description": "The location of the Dockerfile that defines the contents of the container. The path is relative to the folder containing the `devcontainer.json` file."
+ },
+ "context": {
+ "type": "string",
+ "description": "The location of the context folder for building the Docker image. The path is relative to the folder containing the `devcontainer.json` file."
+ }
+ },
+ "required": ["dockerfile"]
+ },
+ {
+ "$ref": "#/definitions/buildOptions"
+ }
+ ],
+ "unevaluatedProperties": false
+ }
+ },
+ "required": ["build"]
+ },
+ {
+ "allOf": [
+ {
+ "type": "object",
+ "properties": {
+ "dockerFile": {
+ "type": "string",
+ "description": "The location of the Dockerfile that defines the contents of the container. The path is relative to the folder containing the `devcontainer.json` file."
+ },
+ "context": {
+ "type": "string",
+ "description": "The location of the context folder for building the Docker image. The path is relative to the folder containing the `devcontainer.json` file."
+ }
+ },
+ "required": ["dockerFile"]
+ },
+ {
+ "type": "object",
+ "properties": {
+ "build": {
+ "description": "Docker build-related options.",
+ "$ref": "#/definitions/buildOptions"
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "buildOptions": {
+ "type": "object",
+ "properties": {
+ "target": {
+ "type": "string",
+ "description": "Target stage in a multi-stage build."
+ },
+ "args": {
+ "type": "object",
+ "additionalProperties": {
+ "type": ["string"]
+ },
+ "description": "Build arguments."
+ },
+ "cacheFrom": {
+ "type": ["string", "array"],
+ "description": "The image to consider as a cache. Use an array to specify multiple images.",
+ "items": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "imageContainer": {
+ "type": "object",
+ "properties": {
+ "image": {
+ "type": "string",
+ "description": "The docker image that will be used to create the container."
+ }
+ },
+ "required": ["image"]
+ },
+ "composeContainer": {
+ "type": "object",
+ "properties": {
+ "dockerComposeFile": {
+ "type": ["string", "array"],
+ "description": "The name of the docker-compose file(s) used to start the services.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "service": {
+ "type": "string",
+ "description": "The service you want to work on. This is considered the primary container for your dev environment which your editor will connect to."
+ },
+ "runServices": {
+ "type": "array",
+ "description": "An array of services that should be started and stopped.",
+ "items": {
+ "type": "string"
+ }
+ },
+ "workspaceFolder": {
+ "type": "string",
+ "description": "The path of the workspace folder inside the container. This is typically the target path of a volume mount in the docker-compose.yml."
+ },
+ "shutdownAction": {
+ "type": "string",
+ "enum": ["none", "stopCompose"],
+ "description": "Action to take when the user disconnects from the primary container in their editor. The default is to stop all of the compose containers."
+ },
+ "overrideCommand": {
+ "type": "boolean",
+ "description": "Whether to overwrite the command specified in the image. The default is false."
+ }
+ },
+ "required": ["dockerComposeFile", "service", "workspaceFolder"]
+ },
+ "Mount": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "enum": ["bind", "volume"],
+ "description": "Mount type."
+ },
+ "source": {
+ "type": "string",
+ "description": "Mount source."
+ },
+ "target": {
+ "type": "string",
+ "description": "Mount target."
+ }
+ },
+ "required": ["type", "source", "target"],
+ "additionalProperties": false
+ }
+ },
+ "oneOf": [
+ {
+ "allOf": [
+ {
+ "oneOf": [
+ {
+ "allOf": [
+ {
+ "oneOf": [
+ {
+ "$ref": "#/definitions/dockerfileContainer"
+ },
+ {
+ "$ref": "#/definitions/imageContainer"
+ }
+ ]
+ },
+ {
+ "$ref": "#/definitions/nonComposeBase"
+ }
+ ]
+ },
+ {
+ "$ref": "#/definitions/composeContainer"
+ }
+ ]
+ },
+ {
+ "$ref": "#/definitions/devContainerCommon"
+ }
+ ]
+ },
+ {
+ "type": "object",
+ "$ref": "#/definitions/devContainerCommon",
+ "additionalProperties": false
+ }
+ ],
+ "unevaluatedProperties": false
+}
diff --git a/schemas/devContainerFeature.schema.json b/devcontainer-feature.schema.json
similarity index 88%
rename from schemas/devContainerFeature.schema.json
rename to devcontainer-feature.schema.json
index 47241616..927ce797 100644
--- a/schemas/devContainerFeature.schema.json
+++ b/devcontainer-feature.schema.json
@@ -8,9 +8,7 @@
"properties": {
"capAdd": {
"description": "Passes docker capabilities to include when creating the dev container.",
- "examples": [
- "SYS_PTRACE"
- ],
+ "examples": ["SYS_PTRACE"],
"items": {
"type": "string"
},
@@ -104,110 +102,72 @@
"type": "boolean"
},
"onCreateCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
+ "type": ["string", "array", "object"],
"description": "A command to run when creating the container. This command is run after \"initializeCommand\" and before \"updateContentCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
"items": {
"type": "string"
},
"additionalProperties": {
- "type": [
- "string",
- "array"
- ],
+ "type": ["string", "array"],
"items": {
"type": "string"
}
}
},
"updateContentCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
+ "type": ["string", "array", "object"],
"description": "A command to run when creating the container and rerun when the workspace content was updated while creating the container. This command is run after \"onCreateCommand\" and before \"postCreateCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
"items": {
"type": "string"
},
"additionalProperties": {
- "type": [
- "string",
- "array"
- ],
+ "type": ["string", "array"],
"items": {
"type": "string"
}
}
},
"postCreateCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
+ "type": ["string", "array", "object"],
"description": "A command to run after creating the container. This command is run after \"updateContentCommand\" and before \"postStartCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
"items": {
"type": "string"
},
"additionalProperties": {
- "type": [
- "string",
- "array"
- ],
+ "type": ["string", "array"],
"items": {
"type": "string"
}
}
},
"postStartCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
+ "type": ["string", "array", "object"],
"description": "A command to run after starting the container. This command is run after \"postCreateCommand\" and before \"postAttachCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
"items": {
"type": "string"
},
"additionalProperties": {
- "type": [
- "string",
- "array"
- ],
+ "type": ["string", "array"],
"items": {
"type": "string"
}
}
},
"postAttachCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
+ "type": ["string", "array", "object"],
"description": "A command to run when attaching to the container. This command is run after \"postStartCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
"items": {
"type": "string"
},
"additionalProperties": {
- "type": [
- "string",
- "array"
- ],
+ "type": ["string", "array"],
"items": {
"type": "string"
}
}
}
},
- "required": [
- "id",
- "version"
- ],
+ "required": ["id", "version"],
"type": "object"
},
"FeatureOption": {
@@ -230,10 +190,7 @@
"type": "string"
}
},
- "required": [
- "type",
- "default"
- ],
+ "required": ["type", "default"],
"type": "object"
},
{
@@ -260,11 +217,7 @@
"type": "string"
}
},
- "required": [
- "type",
- "enum",
- "default"
- ],
+ "required": ["type", "enum", "default"],
"type": "object"
},
{
@@ -291,10 +244,7 @@
"type": "string"
}
},
- "required": [
- "type",
- "default"
- ],
+ "required": ["type", "default"],
"type": "object"
}
]
@@ -313,18 +263,11 @@
},
"type": {
"description": "Type of mount. Can be 'bind' or 'volume'.",
- "enum": [
- "bind",
- "volume"
- ],
+ "enum": ["bind", "volume"],
"type": "string"
}
},
- "required": [
- "type",
- "source",
- "target"
- ],
+ "required": ["type", "source", "target"],
"type": "object"
}
},
@@ -334,4 +277,4 @@
"$ref": "#/definitions/Feature"
}
]
-}
\ No newline at end of file
+}
diff --git a/devcontainer.schema.json b/devcontainer.schema.json
new file mode 100644
index 00000000..7b0727db
--- /dev/null
+++ b/devcontainer.schema.json
@@ -0,0 +1,13 @@
+{
+ "allOf": [
+ {
+ "$ref": "./devcontaine-base.schema.json"
+ },
+ {
+ "$ref": "https://raw.githubusercontent.com/microsoft/vscode/main/extensions/configuration-editing/schemas/devContainer.codespaces.schema.json"
+ },
+ {
+ "$ref": "https://raw.githubusercontent.com/microsoft/vscode/main/extensions/configuration-editing/schemas/devContainer.vscode.schema.json"
+ }
+ ]
+}
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index dd859582..00000000
--- a/docs/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Documentation
-
-Documentation and reference material about development containers and the dev container CLI.
diff --git a/docs/images/README.md b/docs/images/README.md
deleted file mode 100644
index 3be889d2..00000000
--- a/docs/images/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Images
-
-These images are used in READMEs.
diff --git a/docs/images/Slack_Mark-24x24.png b/docs/images/Slack_Mark-24x24.png
deleted file mode 100644
index 18a551d2..00000000
Binary files a/docs/images/Slack_Mark-24x24.png and /dev/null differ
diff --git a/docs/images/Twitter_Social_Icon_24x24.png b/docs/images/Twitter_Social_Icon_24x24.png
deleted file mode 100644
index 0b90a2d8..00000000
Binary files a/docs/images/Twitter_Social_Icon_24x24.png and /dev/null differ
diff --git a/docs/images/gitter-icon-24x24.png b/docs/images/gitter-icon-24x24.png
deleted file mode 100644
index dd010664..00000000
Binary files a/docs/images/gitter-icon-24x24.png and /dev/null differ
diff --git a/docs/images/so-image-24x24.png b/docs/images/so-image-24x24.png
deleted file mode 100644
index 0b68689c..00000000
Binary files a/docs/images/so-image-24x24.png and /dev/null differ
diff --git a/docs/specs/devcontainer-features-distribution.md b/docs/specs/devcontainer-features-distribution.md
deleted file mode 100644
index 9d326959..00000000
--- a/docs/specs/devcontainer-features-distribution.md
+++ /dev/null
@@ -1,188 +0,0 @@
-# Distribution and Discovery of Dev Container Features
-
-**TL;DR Check out the [quick start repository](https://github.com/devcontainers/feature-template) to get started on distributing your own Dev Container Features.**
-
-This specification defines a pattern where community members and organizations can author and self-publish [Dev Container Features](./devcontainer-features.md).
-
-Goals include:
-
-- For Feature authors, create a "self-service" way to publish a Feature, either publicly or privately, that is not centrally controlled.
-- For users, provide the ability to validate the integrity of fetched Feature assets.
-- For users, provide the ability to pin to a particular version (absolute, or semantic version) of a Feature to allow for consistent, repeatable environments.
-- Provide the ability to standardize publishing such that [supporting tools](../docs/specs/supporting-tools.md) may implement their own mechanism to aid Feature discoverability as they see fit.
-
-> **Tip:** This section covers details on the Features specification. If you are looking for summarized information on creating your own Features, see the [template](https://github.com/devcontainers/feature-template) and [core Features](https://github.com/devcontainers/features) repositories.
-
-## Source code
-
-Features source code is stored in a git repository.
-
-For ease of authorship and maintenance, [1..n] features can share a single git repository. This set of features is referred to as a "collection," and will share the same [`devcontainer-collection.json`](#devcontainer-collection.json) file and "namespace" (eg. `/`).
-
-Source code for the set follows the example file structure below:
-
-```
-.
-├── README.md
-├── src
-│ ├── dotnet
-│ │ ├── devcontainer-feature.json
-│ │ ├── install.sh
-│ │ └── ...
-| ├
-│ ├── go
-│ │ ├── devcontainer-feature.json
-│ │ └── install.sh
-| ├── ...
-│ │ ├── devcontainer-feature.json
-│ │ └── install.sh
-├── test
-│ ├── dotnet
-│ │ ├── test.sh
-│ │ └── ...
-│ └── go
-│ | └── test.sh
-| ├── ...
-│ │ └── test.sh
-├── ...
-```
-
-...where `src` is a directory containing a sub-folder with the name of the feature (e.g. `src/dotnet` or `src/go`) with at least a file named `devcontainer-feature.json` that contains the feature metadata, and an `install.sh` script that implementing tools will use as the entrypoint to install the feature.
-
-Each sub-directory should be named such that it matches the `id` field of the `devcontainer-feature.json`. Other files can also be included in the feature's sub-directory, and will be included during the [packaging step](#packaging) alongside the two required files. Any files that are not part of the feature's sub-directory (e.g. outside of `src/dotnet`) will not included in the [packaging step](#packaging).
-
-Optionally, a mirrored `test` directory can be included with an accompanying `test.sh` script. Implementing tools may use this to run tests against the given feature.
-
-## Versioning
-
-Each feature is individually [versioned according to the semver specification](https://semver.org/). The `version` property in the respective `devcontainer-feature.json` file is parsed to determine if the feature should be republished.
-
-Tooling that handles publishing features will not republish features if that exact version has already been published; however, tooling must republish major and minor versions in accordance with the semver specification.
-
-## Packaging
-
-Features are distributed as tarballs. The tarball contains the entire contents of the feature sub-directory, including the `devcontainer-feature.json`, `install.sh`, and any other files in the directory.
-
-The tarball is named `devcontainer-feature-.tgz`, where `` is the feature's `id` field.
-
-A reference implementation for packaging and distributing features is provided as a GitHub Action (https://github.com/devcontainers/action).
-
-
-### devcontainer-collection.json
-
-The `devcontainer-collection.json` is an auto-generated metadata file.
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `sourceInformation` | object | Metadata from the implementing packaging tool. |
-| `features` | array | The list of features that are contained in this collection.|
-
-Each features's `devcontainer-feature.json` metadata file is appended into the `features` top-level array.
-
-## Distribution
-
-There are several supported ways to distribute Features. Distribution is handled by the implementing packaging tool such as the [Dev Container CLI](https://github.com/devcontainers/cli) or [Dev Container Publish GitHub Action](https://github.com/marketplace/actions/dev-container-publish). See the [quick start repository](https://github.com/devcontainers/feature-template) for a full working example.
-
-> Feature identifiers should be provided lowercase by an author. If not, an implementing packaging tool should normalize the identifier into lowercase for any internal representation.
-
-A user references a distributed feature in a `devcontainer.json` as defined in ['referencing a feature'](./devcontainer-features.md#Referencing-a-feature).
-
-### OCI Registry
-
-An OCI registry that implements the [OCI Artifact Distribution Specification](https://github.com/opencontainers/distribution-spec) serves as the primary distribution mechanism for features.
-
-Each packaged feature is pushed to the registry following the naming convention `//[:version]`, where version is the major, minor, and patch version of the feature, according to the semver specification.
-
-> **Note:** The `namespace` is a unique indentifier for the collection of features. There are no strict rules for the `namespace`; however, one pattern is to set `namespace` equal to source repository's `/`. The `namespace` should be lowercase, following [the regex provided in the OCI specification](https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pulling-manifests).
-
-A custom media type `application/vnd.devcontainers` and `application/vnd.devcontainers.layer.v1+tar` are used as demonstrated below.
-
-For example, the `go` feature in the `devcontainers/features` namespace at version `1.2.3` would be pushed to the ghcr.io OCI registry.
-
-> **Note:** The example below uses [`oras`](https://oras.land/) for demonstration purposes. A supporting tool should directly implement the required functionality from the aforementioned OCI artifact distribution specification.
-
-```bash
-# ghcr.io/devcontainers/features/go:1
-REGISTRY=ghcr.io
-NAMESPACE=devcontainers/features
-FEATURE=go
-
-ARTIFACT_PATH=devcontainer-feature-go.tgz
-
-for VERSION in 1 1.2 1.2.3 latest
-do
- oras push ${REGISTRY}/${NAMESPACE}/${FEATURE}:${VERSION} \
- --manifest-config /dev/null:application/vnd.devcontainers \
- ./${ARTIFACT_PATH}:application/vnd.devcontainers.layer.v1+tar
-done
-
-```
-
-The "namespace" is the globally identifiable name for the collection of features. (eg: `owner/repo` for the source code's git repository).
-
-The auto-generated `devcontainer-collection.json` is pushed to the registry with the same `namespace` as above and no accompanying `feature` name. The collection file is always tagged as `latest`.
-
-```bash
-# ghcr.io/devcontainers/features
-REGISTRY=ghcr.io
-NAMESPACE=devcontainers/features
-
-oras push ${REGISTRY}/${NAMESPACE}:latest \
- --manifest-config /dev/null:application/vnd.devcontainers \
- ./devcontainer-collection.json:application/vnd.devcontainers.collection.layer.v1+json
-```
-
-### Directly referencing a tarball
-
-A Feature can be referenced directly in a user's [`devcontainer.json`](/docs/specs/devcontainer-reference.md#devcontainerjson) file by HTTPS URI that points to the tarball from the [package step](#packaging).
-
-The `.tgz` archive file must be named `devcontainer-feature-.tgz`.
-
-### Locally referenced Features
-
-Instead of publishing a Feature to an OCI registry, a Feature's source code may be referenced from a local folder. Locally referencing a Feature may be useful when first authoring a Feature.
-
-A local Feature is referenced in the devcontainer's `feature` object **relative to the folder containing the project's `devcontainer.json`**.
-
-Additional constraints exists when including local Features in a project:
-
-* The project must have a `.devcontainer/` folder at the root of the [**project workspace folder**](/docs/specs/devcontainer-reference.md#project-workspace-folder).
-
-* A local Feature's source code **must** be contained within a sub-folder of the `.devcontainer/ folder`.
-
-* The sub-folder name **must** match the Feature's `id` field.
-
-* A local Feature may **not** be referenced by absolute path.
-
-* The local Feature's sub-folder **must** contain at least a `devcontainer-feature.json` file and `install.sh` entrypoint script, mirroring the [previously outlined file structure](#Source-code).
-
-
-The relative path is provided using unix-style path syntax (eg `./myFeature`) regardless of the host operating system.
-
-An example project is illustrated below:
-
-```
-.
-├── .devcontainer/
-│ ├── localFeatureA/
-│ │ ├── devcontainer-feature.json
-│ │ ├── install.sh
-│ │ └── ...
-│ ├── localFeatureB/
-│ │ ├── devcontainer-feature.json
-│ │ ├── install.sh
-│ │ └── ...
-│ ├── devcontainer.json
-```
-
-##### devcontainer.json
-```jsonc
-{
- // ...
- "features": {
- "./localFeatureA": {},
- "./localFeatureB": {}
- }
-
-}
-```
diff --git a/docs/specs/devcontainer-features.md b/docs/specs/devcontainer-features.md
deleted file mode 100644
index af37c6bd..00000000
--- a/docs/specs/devcontainer-features.md
+++ /dev/null
@@ -1,434 +0,0 @@
-# Dev Container Features reference
-
-Development container "Features" are self-contained, shareable units of installation code and development container configuration. The name comes from the idea that referencing one of them allows you to quickly and easily add more tooling, runtime, or library "Features" into your development container for you or your collaborators to use.
-
-> **Note:** While Features may be installed on top of any base image, the implementation of a Feature might restrict it to a subset of possible base images.
->
-> For example, some Features may be authored to work with a certain linux distro (e.g. debian-based images that use the `apt` package manager).
-
-Feature metadata is captured by a `devcontainer-feature.json` file in the root folder of the Feature.
-
-> **Tip:** This section covers details on the Features specification. If you are looking for summarized information on creating your own Features, see the [template](https://github.com/devcontainers/feature-template) and [core Features](https://github.com/devcontainers/features) repositories.
-
-## Folder structure
-
-A Feature is a self contained entity in a folder with at least a `devcontainer-feature.json` and `install.sh` entrypoint script. Additional files are permitted and are packaged along side the required files.
-
-```
-+-- feature
-| +-- devcontainer-feature.json
-| +-- install.sh
-| +-- (other files)
-```
-
-## `devcontainer-feature.json` properties
-
-The `devcontainer-feature.json` file defines metadata about a given Feature.
-
-All properties are optional **except for `id`, `version`, and `name`**.
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `id` | string | **Required**: Identifier of the Feature. Must be unique in the context of the repository where the Feature exists and must match the name of the directory where the `devcontainer-feature.json` resides. ID should be provided lowercase. |
-| `version` | string | **Required**: The semantic version of the Feature (e.g: `1.0.0`). |
-| `name` | string | **Required**: A "human-friendly" display name for the Feature. |
-| `description` | string | Description of the Feature. |
-| `documentationURL` | string | Url that points to the documentation of the Feature. |
-| `licenseURL` | string | Url that points to the license of the Feature. |
-| `keywords` | array | List of strings relevant to a user that would search for this Feature. |
-| `options` | object | A map of options that will be passed as environment variables to the execution of the script. |
-| `containerEnv` | object | A set of name value pairs that sets or overrides environment variables. |
-| `privileged` | boolean | Sets [privileged mode](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) for the container (required by things like docker-in-docker) when the Feature is used. |
-| `init` | boolean | Adds the [tiny init](https://github.com/RKrahl/tiny-init) process to the container (`--init`) when the Feature is used. |
-| `capAdd` | array | Adds container [capabilities](https://docs.docker.com/engine/security/#linux-kernel-capabilities) when the Feature is used. |
-| `securityOpt` | array | Sets container security options like updating the [seccomp profile](https://docs.docker.com/engine/security/seccomp/) when the Feature is used. |
-| `entrypoint` | string | Set if the Feature requires an "entrypoint" script that should fire at container start up. |
-| `customizations` | object | Product specific properties, each namespace under `customizations` is treated as a separate set of properties. For each of this sets the object is parsed, values are replaced while arrays are set as a union. |
-| `installsAfter` | array | Array of ID's of Features (omitting a version tag) that should execute before this one. Allows control for Feature authors on soft dependencies between different Features. |
-| `legacyIds` | array | Array of old IDs used to publish this Feature. The property is useful for renaming a currently published Feature within a single namespace. |
-| `deprecated` | boolean | Indicates that the Feature is deprecated, and will not receive any further updates/support. This property is intended to be used by the supporting tools for highlighting Feature deprecation. |
-| `mounts` | object | Defaults to unset. Cross-orchestrator way to add additional mounts to a container. Each value is an object that accepts the same values as the [Docker CLI `--mount` flag](https://docs.docker.com/engine/reference/commandline/run/#mount). The Pre-defined [devcontainerId](./devcontainerjson-reference.md/#variables-in-devcontainerjson) variable may be referenced in the value. For example:
`"mounts": [{ "source": "dind-var-lib-docker", "target": "/var/lib/docker", "type": "volume" }]` |
-
-
-### Lifecycle Hooks
-
-The following lifecycle hooks may be declared as properties of `devcontainer-feature.json`.
-
-| Property | Type|
-| :--- | :--- |
-| `onCreateCommand` | [string, array, object](/docs/specs/devcontainerjson-reference.md#formatting-string-vs-array-properties)|
-| `updateContentCommand` | [string, array, object](/docs/specs/devcontainerjson-reference.md#formatting-string-vs-array-properties)|
-| `postCreateCommand` | [string, array, object](/docs/specs/devcontainerjson-reference.md#formatting-string-vs-array-properties)|
-| `postStartCommand` | [string, array, object](/docs/specs/devcontainerjson-reference.md#formatting-string-vs-array-properties) |
-| `postAttachCommand` | [string, array, object](/docs/specs/devcontainerjson-reference.md#formatting-string-vs-array-properties) |
-
-#### Behavior
-
-Each property mirrors the behavior of the matching property in [`devcontainer.json`](/docs/specs/devcontainerjson-reference.md#Lifecycle-scripts), including the behavior that commands are executed from the context of the [project workspace folder](https://containers.dev/implementors/spec/#project-workspace-folder).
-
-For each lifecycle hook (in [Feature installation order](https://containers.dev/implementors/features/#installation-order)), each command contributed by a Feature is executed in sequence (blocking the next command from executing). Commands provided by Features are always executed _before_ any user-provided lifecycle commands (i.e: in the `devcontainer.json`).
-
-If a Feature provides a given command with the [object syntax](/docs/specs/devcontainerjson-reference.md#formatting-string-vs-array-properties), all commands within that group are executed in parallel, but still blocking commands from subsequent Features and/or the `devcontainer.json`.
-
-> NOTE: These properties are stored within [image metadata](https://github.com/devcontainers/spec/blob/joshspicer/lifecycle_hook_feature_spec/docs/specs/devcontainer-reference.md#merge-logic).
-
-### The `options` property
-
-The options property is contains a map of option IDs and their related configuration settings. The ID becomes the name of the environment variable in all caps. See [option resolution](#option-resolution) for more details. For example:
-
-```json
-{
- "options": {
- "optionIdGoesHere": {
- "type": "string",
- "description": "Description of the option",
- "proposals": ["value1", "value2"],
- "default": "value1"
- }
- }
-}
-```
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `optionId` | string | ID of the option that is converted into an all-caps environment variable with the selected value in it. |
-| `optionId.type` | string | Type of the option. Valid types are currently: `boolean`, `string` |
-| `optionId.proposals` | array | A list of suggested string values. Free-form values **are** allowed. Omit when using `optionId.enum`. |
-| `optionId.enum` | array | A strict list of allowed string values. Free-form values are **not** allowed. Omit when using `optionId.proposals`. |
-| `optionId.default` | string or boolean | Default value for the option. |
-| `optionId.description` | string | Description for the option. |
-
-### User environment variables
-
-Feature scripts run as the `root` user and sometimes need to know which user account the dev container will be used with.
-
-`_REMOTE_USER` and `_CONTAINER_USER` environment variables are passsed to the Features scripts with `_CONTAINER_USER` being the container's user and `_REMOTE_USER` being the configured `remoteUser`. If no `remoteUser` is configured, `_REMOTE_USER` is set to the same value as `_CONTAINER_USER`.
-
-Additionally, the home folders of the two users are passed to the Feature scripts as `_REMOTE_USER_HOME` and `_CONTAINER_USER_HOME` environment variables.
-
-The container user can be set with `containerUser` in the devcontainer.json and image metadata, `user` in the docker-compose.yml, `USER` in the Dockerfile, and can be passed down from the base image.
-
-### Dev Container ID
-
-An identifier will be referred to as `${devcontainerId}` in the devcontainer.json and the Feature metadata and that will be replaced with the dev container's id. It should only be used in parts of the configuration and metadata that is not used for building the image because that would otherwise prevent pre-building the image at a time when the dev container's id is not known yet. Excluding boolean, numbers and enum properties the properties supporting `${devcontainerId}` in the Feature metadata are: `entrypoint`, `mounts`, `customizations`.
-
-Implementations can choose how to compute this identifier. They must ensure that it is unique among other dev containers on the same Docker host and that it is stable across rebuilds of dev containers. The identifier must only contain alphanumeric characters. We describe a way to do this below.
-
-#### Label-based Implementation
-
-The following assumes that a dev container can be identified among other dev containers on the same Docker host by a set of labels on the container. Implementations may choose to follow this approach.
-
-The identifier is derived from the set of container labels uniquely identifying the dev container. It is up to the implementation to choose these labels. E.g., if the dev container is based on a local folder the label could be named `devcontainer.local_folder` and have the local folder's path as its value.
-
-E.g., the [`ghcr.io/devcontainers/features/docker-in-docker` Feature](https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json) could use the dev container id with:
-
-```jsonc
-{
- "id": "docker-in-docker",
- "version": "1.0.4",
- // ...
- "mounts": [
- {
- "source": "dind-var-lib-docker-${devcontainerId}",
- "target": "/var/lib/docker",
- "type": "volume"
- }
- ]
-}
-```
-
-#### Label-based Computation
-
-- Input the labels as a JSON object with the object's keys being the label names and the object's values being the labels' values.
- - To ensure implementations get to the same result, the object keys must be sorted and any optional whitespace outside of the keys and values must be removed.
-- Compute a SHA-256 hash from the UTF-8 encoded input string.
-- Use a base-32 encoded representation left-padded with '0' to 52 characters as the result.
-
-JavaScript implementation taking an object with the labels as argument and returning a string as the result:
-
-```js
-const crypto = require('crypto');
-function uniqueIdForLabels(idLabels) {
- const stringInput = JSON.stringify(idLabels, Object.keys(idLabels).sort()); // sort properties
- const bufferInput = Buffer.from(stringInput, 'utf-8');
- const hash = crypto.createHash('sha256')
- .update(bufferInput)
- .digest();
- const uniqueId = BigInt(`0x${hash.toString('hex')}`)
- .toString(32)
- .padStart(52, '0');
- return uniqueId;
-}
-```
-
-## devcontainer.json properties
-
-Features are referenced in a user's [`devcontainer.json`](/docs/specs/devcontainer-reference.md#devcontainerjson) under the top level `features` object.
-
-A user can specify an arbitrary number of Features. At build time, these Features will be installed in an order defined by a combination of the [installation order rules and implementation](#Installation-Order).
-
-A single Feature is provided as a key/value pair, where the key is the Feature identifier, and the value is an object containing "options" (or empty for "default"). Each key in the Feature object must be unique.
-
-These options are sourced as environment variables at build-time, as specified in [Option Resolution](#Option-Resolution).
-
-
-Below is a valid `features` object provided as an example.
-```jsonc
-"features": {
- "ghcr.io/user/repo/go": {},
- "ghcr.io/user/repo1/go:1": {},
- "ghcr.io/user/repo2/go:latest": {},
- "https://github.com/user/repo/releases/devcontainer-feature-go.tgz": {
- "optionA": "value"
- },
- "./myGoFeature": {
- "optionA": true,
- "optionB": "hello",
- "version" : "1.0.0"
- }
-}
-```
-
-> Note: The `:latest` version annotation is added implicitly if omitted. To pin to a specific package version ([example](https://github.com/devcontainers/features/pkgs/container/features/go/versions)), append it to the end of the Feature.
-
-An option's value can be provided as either a `string` or `boolean`, and should match what is expected by the Feature in the `devcontainer-feature.json` file.
-
-As a shorthand, the value of a `feature` can be provided as a single string. This string is mapped to an option called `version`. In the example below, both examples are equivalent.
-
-```jsonc
-"features": {
- "ghcr.io/owner/repo/go": "1.18"
-}
-```
-```jsonc
-"features": {
- "ghcr.io/owner/repo/go": {
- "version": "1.18"
- }
-}
-```
-
-### Referencing a feature
-
-The `id` format specified dictates how a supporting tool will locate and download a given Feature. `id` is one of the following:
-
-| Type | Description | Example |
-| :--- | :--- | :--- |
-| `//[:]` | Reference to feature in OCI registry(*) | `ghcr.io/user/repo/go`
`ghcr.io/user/repo/go:1`
`ghcr.io/user/repo/go:latest`|
-| `https://` | Direct HTTPS URI to a tarball. | `https://github.com/user/repo/releases/devcontainer-feature-go.tgz` |
-| `./`| A relative directory(**) to folder containing a devcontainer-feature.json. | `./myGoFeature` |
-
-Feature identifiers should be assumed to be case-insensitive and should be normalized to lowercase.
-
-(*) OCI registry must implement the [OCI Artifact Distribution Specification](https://github.com/opencontainers/distribution-spec). Some implementors can be [found here](https://oras.land/implementors/).
-
-(**) The provided path is always relative to the folder containing the `devcontainer.json`. Further requirements are outlined in the [Locally Referenced Addendum](./devcontainer-features-distribution.md#locally-referenced-features)
-
-## Versioning
-
-Each Feature is individually [versioned according to the semver specification](https://semver.org/). The `version` property in the respective `devcontainer-feature.json` file is updated to increment the Feature's version.
-
-Tooling that handles releasing Features will not republish Features if that exact version has already been published; however, tooling must republish major and minor versions in accordance with the semver specification.
-
-## Authoring
-
-Features can be authored in a number of languages, the most straightforward being bash scripts. If a Feature is authored in a different language information about it should be included in the metadata so that users can make an informed choice about it.
-
-Reference information about the application required to execute the Feature should be included in `devcontainer-feature.json` in the metadata section.
-
-Applications should default to `/bin/sh` for Features that do not include this information.
-
-If the Feature is included in a folder as part of the repository that contains `devcontainer.json`, no other steps are necessary.
-
-## Release
-
-_For information on distributing Features, see [devcontainer-features-distribution.md](./devcontainer-features-distribution.md)._
-
-## Execution
-
-### Invoking `install.sh`
-
-The `install.sh` script for each Feature should be executed as `root` during a container image build. This allows the script to add needed OS dependencies or settings that could not otherwise be modified. This also allows the script to switch into another user's context using the `su` command (e.g., `su ${USERNAME} -c "command-goes-here"`). In combination, this allows both root and non-root image modifications to occur even if `sudo` is not present in the base image for security reasons.
-
-To ensure that the appropriate shell is used, the execute bit should be set on `install.sh` and the file invoked directly (e.g. `chmod +x install.sh && ./install.sh`).
-
-> **Note:** It is recommended that Feature authors write `install.sh` using a shell available by default in their supported distributions (e.g., `bash` in Debian/Ubuntu or Fedora, `sh` in Alpine). In the event a different shell is required (e.g., `fish`), `install.sh` can be used to boostrap by checking for the presence of the desired shell, installing it if needed, and then invoking a secondary script using the shell.
->
-> The `install.sh` file can similarly be used to bootstrap something written in a compiled language like Go. Given the increasing likelihood that a Feature needs to work on both x86_64 and arm64-based devices (e.g., Apple Silicon Macs), `install.sh` can detect the current architecture (e.g., using something like `uname -m` or `dpkg --print-architecture`), and then invoke the right executable for that architecture.
-
-### Installation order
-
-By default, Features are installed on top of a base image in an order determined as optimal by the implementing tool.
-
-If any of the following properties are provided in the Feature's `devcontainer-feature.json`, or the user's `devcontainer.json`, the order indicated by these propert(ies) are respected (with decreasing precedence).
-
-1. The `overrideFeatureInstallOrder` property in user's `devcontainer.json`. Allows users to control the order of execution of their Features.
-2. The `installsAfter` property defined as part of a Feature's `devcontainer-feature.json`.
-
-#### (1) The `overrideFeatureInstallOrder` property
-
-This property is declared by the user in their `devcontainer.json` file.
-
-Any **un-versioned** Feature IDs listed in this array will be installed before all other Features, in the provided order. Any omitted Features will be installed in an order selected by the implementing tool, or ordered via the `installsAfter` property _after_ any Features listed in the `overrideFeatureInstallOrder` array, if applicable.
-
-All un-versioned Feature `id`s provided in `overrideFeatureInstallOrder` must also exist in the `features` property of a user's `devcontainer.json`. For instance, all the Features which follows the OCI registry format would include everything except for the label that contains the version (`//` without the `:`).
-
-Example:
-```
- "features": {
- "ghcr.io/devcontainers/features/java:1",
- "ghcr.io/devcontainers/features/node:1",
- },
- "overrideFeatureInstallOrder": [
- "ghcr.io/devcontainers/features/node"
- ]
-```
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `overrideFeatureInstallOrder` | array | Array consisting of the Feature `id` (without the semantic version) of Features in the order the user wants them to be installed. |
-
-#### (2) The `installsAfter` Feature property
-
-This property is defined in an individual feature's `devcontainer-feature.json` file by the feature author. `installsAfter` allows an author to provide the tooling hints on loose dependencies between Features.
-
-> This property is mostly useful for optimizing build time (by reordering the Feature installation to reduce installing a required CLI twice, for example). Ideally, all Features should be able to fully install themselves without requiring another Feature to be pre-installed.
-
-After `overrideFeatureInstallOrder` is resolved, any remaining Features that declare an `installsAfter` must be installed after the Features declared in the property, provided that the Features have also been declared in the `features` property.
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `installsAfter` | array | Array consisting of the Feature `id` (omitting a version tag) that should be installed before the given Feature |
-
-### Option Resolution
-
-A Feature's 'options' - specified as the value of a single Feature key/value pair in the user's `devcontainer.json` - are passed to the Feature as environment variables.
-
-A supporting tool will parse the `options` object provided by the user. If a value is provided for a Feature, it will be emitted to a file named `devcontainer-features.env` following the format `=`.
-
-To ensure a option that is valid as an environment variable, the follow substitutions are performed.
-
-```javascript
-(str: string) => str
- .replace(/[^\w_]/g, '_')
- .replace(/^[\d_]+/g, '_')
- .toUpperCase();
-```
-
-This file is sourced at build-time for the Feature `install.sh` entrypoint script to handle.
-
-Any options defined by a Feature's `devcontainer-feature.json` that are omitted in the user's `devcontainer.json` will be implicitly exported as its default value.
-
-### Option resolution example
-
-Suppose a `python` Feature has the following `options` parameters declared in the `devcontainer-feature.json` file:
-
-```jsonc
-// ...
-"options": {
- "version": {
- "type": "string",
- "enum": ["latest", "3.10", "3.9", "3.8", "3.7", "3.6"],
- "default": "latest",
- "description": "Select a Python version to install."
- },
- "pip": {
- "type": "boolean",
- "default": true,
- "description": "Installs pip"
- },
- "optimize": {
- "type": "boolean",
- "default": true,
- "description": "Optimize python installation"
- }
-}
-```
-
-The user's `devcontainer.json` declared the python Feature like so
-
-```jsonc
-
-"features": {
- "python": {
- "version": "3.10",
- "pip": false
- }
-}
-```
-The emitted environment variables will be:
-
-```env
-VERSION="3.10"
-PIP="false"
-OPTIMIZE="true"
-```
-
-These will be sourced and visible to the `install.sh` entrypoint script. The following `install.sh`...
-
-
-```bash
-#!/usr/bin/env bash
-
-echo "Version is $VERSION"
-echo "Pip? $PIP"
-echo "Optimize? $OPTIMIZE"
-```
-
-... outputs the following:
-```
-Version is 3.10
-Pip? false
-Optimize? true
-```
-
-### Steps to rename a Feature
-
-1. Update the Feature [source code](./devcontainer-features-distribution.md#source-code) folder and the `id` property in the [devcontainer-feature.json properties](#devcontainer-featurejson-properties) to reflect the new `id`. Other properties (`name`, `documentationUrl`, etc.) can optionally be updated during this step.
-2. Add or update the `legacyIds` property to the Feature, including the previously used `id`.
-3. Bump the semantic version of the Feature.
-4. Rerun the `devcontainer features publish` command, or equivalent tool that implements the [Features distribution specification](./features-distribution/#distribution).
-
-#### Example: Renaming a Feature
-
-Let's say we currently have a `docker-from-docker` Feature 👇
-
-Current `devcontainer-feature.json` :
-
-```jsonc
-{
- "id": "docker-from-docker",
- "version": "2.0.1",
- "name": "Docker (Docker-from-Docker)",
- "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-from-docker",
- ....
-}
-```
-
-We'd want to rename this Feature to `docker-outside-of-docker`. The source code folder of the Feature will be updated to `docker-outside-of-docker` and the updated `devcontainer-feature.json` will look like 👇
-
-```jsonc
-{
- "id": "docker-outside-of-docker",
- "version": "2.0.2",
- "name": "Docker (Docker-outside-of-Docker)",
- "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-outside-of-docker",
- "legacyIds": [
- "docker-from-docker"
- ]
- ....
-}
-```
-
-**Note** - The semantic version of the Feature defined by the `version` property should be **continued** and should not be restarted at `1.0.0`.
-
-### Implementation notes
-
-There are several things to keep in mind for an application that implements Features:
-
-- The order of execution of Features is determined by the application, based on the `installsAfter` property used by feature authors. It can be overridden by users if necessary with the `overrideFeatureInstallOrder` in `devcontainer.json`.
-- Features are used to create an image that can be used to create a container or not.
-- Parameters like `privileged`, `init` are included if just 1 Feature requires them.
-- Parameters like `capAdd`, `securityOp` are concatenated.
-- `containerEnv` is added before the Feature is executed as `ENV` commands in the Dockerfile.
-- Each Feature script executes as its own layer to aid in caching and rebuilding.
diff --git a/docs/specs/devcontainer-reference.md b/docs/specs/devcontainer-reference.md
deleted file mode 100644
index 7014805e..00000000
--- a/docs/specs/devcontainer-reference.md
+++ /dev/null
@@ -1,287 +0,0 @@
-# Dev container specification
-
-The purpose of the **development container** specification is to provide a way to enrich containers with the content and metadata necessary to enable development inside them. These container **environments** should be easy to use, create, and recreate.
-
-A **development container** is a container in which a user can develop an application. Tools that want to implement this specification should provide a set of features/commands that give more flexibility to users and allow **development containers** to scale to large development groups.
-
-An **environment** is defined as a logical instance of one or more **development containers**, along with any needed side-car containers. An environment is based on one set of metadata that can be managed as a single unit. Users can create multiple **environments** from the same configuration metadata for different purposes.
-
-# Metadata
-
-**Development containers** allow one to define a repeatable development environment for a user or team of developers that includes the execution environment the application needs. A development container defines an environment in which you develop your application before you are ready to deploy. While deployment and development containers may resemble one another, you may not want to include tools in a deployment image that you use during development and you may need to use different secrets or other settings.
-
-Furthermore, working inside a development container can require additional **metadata** to drive tooling or service experiences than you would normally need with a production container. Providing a structured and consistent form for this metadata is a core part of this specification.
-
-## devcontainer.json
-
-While the structure of this metadata is critical, it is also important to call out how this data can be represented on disk where appropriate. While other representations may be added over time, metadata can be stored in a JSON with Comments file called `devcontainer.json` today. Products using it should expect to find a devcontainer.json file in one or more of the following locations (in order of precedence):
-
-- .devcontainer/devcontainer.json
-- .devcontainer.json
-- .devcontainer/``/devcontainer.json (where `` is a sub-folder, one level deep)
-
-It is valid that these files may exist in more than one location, so consider providing a mechanism for users to select one when appropriate.
-
-## Image Metadata
-
-Certain dev container metadata properties can be stored in an image label as an array of metadata snippets. This allows them to be stored in prebuilt images, such that, the image and its related configuration are self-contained. These contents should then be merged with any local devcontainer.json file contents at the time the container is created. An array is used so subsequent image builds can simply append changes to the array rather than attempting to merge at that point - which improves compatibility with arbitrary image build systems.
-
-Metadata should be representative of with the following structure, using one entry per [Dev Container Feature](../features) and devcontainer.json (see table below for the full list):
-
-
-```json
-[
- {
- "id"?: string,
- "init"?: boolean,
- "privileged"?: boolean,
- "capAdd"?: string[],
- "securityOpt"?: string[],
- "entrypoint"?: string,
- "mounts"?: [],
- ...
- "customizations"?: {
- ...
- }
- },
- ...
-]
-```
-
-To simplify adding this metadata for other tools, we also support having a single top-level object with the same properties.
-
-The metadata is added to the image as a `devcontainer.metadata` label with a JSON string value representing the above array or single object.
-
-### Merge Logic
-
-To apply the metadata together with a user's devcontainer.json at runtime the following merge logic by property is used. The table also notes which properties are currently supported coming from the devcontainer.json and which from the feature metadata, this will change over time as we add more properties.
-
-| Property | Type/Format | Merge Logic | devcontainer.json | devcontainer-feature.json |
-| -------- | ----------- | ----------- | :---------------: | :--------------: |
-| `id` | E.g., `ghcr.io/devcontainers/features/node:1` | Not merged. | | x |
-| `init` | `boolean` | `true` if at least one is `true`, `false` otherwise. | x | x |
-| `privileged` | `boolean` | `true` if at least one is `true`, `false` otherwise. | x | x |
-| `capAdd` | `string[]` | Union of all `capAdd` arrays without duplicates. | x | x |
-| `securityOpt` | `string[]` | Union of all `securityOpt` arrays without duplicates. | x | x |
-| `entrypoint` | `string` | Collected list of all entrypoints. | | x |
-| `mounts` | `(string \| { type, src, dst })[]` | Collected list of all mountpoints. Conflicts: Last source wins. | x | x |
-| `onCreateCommand` | `string \| string[] \| {[key: string]: string \| string[]}` | Collected list of all onCreateCommands. | x | x |
-| `updateContentCommand` | `string \| string[] \| {[key: string]: string \| string[]}` | Collected list of all updateContentCommands. | x | x |
-| `postCreateCommand` | `string \| string[] \| {[key: string]: string \| string[]}` | Collected list of all postCreateCommands. | x | x |
-| `postStartCommand` | `string \| string[] \| {[key: string]: string \| string[]}` | Collected list of all postStartCommands. | x | x |
-| `postAttachCommand` | `string \| string[] \| {[key: string]: string \| string[]}` | Collected list of all postAttachCommands. | x | x |
-| `waitFor` | enum | Last value wins. | x | |
-| `customizations` | Object of tool-specific customizations. | Merging is left to the tools. | x | x |
-| `containerUser` | `string` | Last value wins. | x | |
-| `remoteUser` | `string` | Last value wins. | x | |
-| `userEnvProbe` | `string` (enum) | Last value wins. | x | |
-| `remoteEnv` | Object of strings. | Per variable, last value wins. | x | |
-| `containerEnv` | Object of strings. | Per variable, last value wins. | x | |
-| `overrideCommand` | `boolean` | Last value wins. | x | |
-| `portsAttributes` | Map of ports to attributes. | Per port (not per port attribute), last value wins. | x | |
-| `otherPortsAttributes` | Port attributes. | Last value wins (not per port attribute). | x | |
-| `forwardPorts` | `(number \| string)[]` | Union of all ports without duplicates. Last one wins (when mapping changes). | x | |
-| `shutdownAction` | `string` (enum) | Last value wins. | x | |
-| `updateRemoteUserUID` | `boolean` | Last value wins. | x | |
-| `hostRequirements` | `cpus`, `memory`, `storage` | Max value wins. | x | |
-
-Variables in string values will be substituted at the time the value is applied. When the order matters, the devcontainer.json is considered last.
-
-### Notes
-
-- Passing the label as a `LABEL` instruction in the Dockerfile:
- - The size limit on Dockerfiles is around 1.3MB. The line length is limited to 65k characters.
- - Using one line per feature should allow for making full use of these limits.
-- Passing the label as a command line argument:
- - There is no size limit documented for labels, but the daemon returns an error when the request header is >500kb.
- - The 500kb limit is shared, so we cannot use a second label in the same build to avoid it.
- - If/when this becomes an issue we could embed the metadata as a file in the image (e.g., with a label indicating it).
-
-# Orchestration options
-
-A core principle of this specification is to seek to enrich existing container orchestrator formats with development container metadata where appropriate rather than replacing them. As a result, the metadata schema includes a set of optional properties for interoperating with different orchestrators. Today, the specification includes scenario-specific properties for working without a container orchestrator (by directly referencing an image or Dockerfile) and for using Docker Compose as a simple multi-container orchestrator. At the same time, this specification leaves space for further development and implementation of other orchestrator mechanisms and file formats.
-
-The following section describes the differences between those that are supported now.
-
-## Image based
-
-Image based configurations only reference an image that should be reachable and downloadable through `docker pull` commands. Logins and tokens required for these operations are execution environment specific. The only required parameter is `image`. The details are [here](devcontainerjson-reference.md#image-or-dockerfile-specific-properties).
-
-## Dockerfile based
-
-These configurations are defined as using a `Dockerfile` to define the starting point of the **development containers**. As with image based configurations, it is assumed that any base images are already reachable by **Docker** when performing a `docker build` command. The only required parameter in this case is the relative reference to the `Dockerfile` in `build.dockerfile`. The details are [here](devcontainerjson-reference.md#image-or-dockerfile-specific-properties).
-
-There are multiple properties that allow users to control how `docker build` works:
-
-- `build.context`
-- `build.args`
-- `build.target`
-- `build.cacheFrom`
-
-## Docker Compose based
-
-Docker Compose configurations use `docker-compose` (which may be Docker Compose V1 or aliased Docker Compose V2) to create and manage a set of containers required for an application. As with the other configurations, any images required for this operation are assumed to be reachable. The required parameters are:
-
-- `dockerComposeFile`: the reference to the Docker Compose file(s) to be used.
-- `service`: declares the **main** container that will be used for all other operations. Tools are assumed to also use this parameter to connect to the **development container**, although they can provide facilities to connect to the other containers as required by the user.
-- `runServices`: an optional property that indicates the set of services in the `docker-compose` configuration that should be started or stopped with the environment.
-
-It is important to note that **image** and **dockerfile** properties are not needed since Docker Compose supports them natively in the format.
-
-# Other options
-
-In addition to the configuration options explained above, there are other settings that apply when creating **development containers** to facilitate their use by developers.
-
-A complete list of available metadata properties and their purposes can be found in the [`devcontainer.json` reference](devcontainerjson-reference.md). However, we will describe the critical ones below in more detail.
-
-## Environment Variables
-
-Environment variables can be set at different points in the dev container lifecycle. With this in mind, **development containers** support two classes of environment variables:
-
-* **Container**: These variables are part of the container when it is created and are available at all points in its lifecycle. This concept is native to containers and can be set in the container image itself, using `containerEnv` for **image** and **Dockerfile** scenarios or using orchestrator specific properties like `env` in **Docker Compose** files.
-* **Remote**: These variables should be set by a **development container** supporting tool as part of configuring its runtime environment. Users can set these using the `remoteEnv` property and implementing tools or services may add their own for specific scenarios (e.g., secrets). These variables can change during the lifetime of the container, and are added after the container's `ENTRYPOINT` has fired.
-
-The reason for this separation is it allows for the use of information not available at image build time and simplifies updating the environment for project/repository specific needs without modifying an image. With this in in mind, it's important to note that implementing tools should also support the [dynamic variable syntax](devcontainerjson-reference.md#variables-in-devcontainerjson) described in the metadata reference document.
-
-
-Another notable and important environment variable related property is **`userEnvProbe`**. Implementing tools should use this property to "probe" for expected environment variables using the specified type of shell. However, it does not specify that this type of shell needs to be used for all sub-processes (given the performance impact). Instead, "probed" environment variables should be merged with Remote environment variables for any processes the implementer injects after the container is created. This allows implementors to emulate developer expected behaviors around values added to their profile and rc files.
-
-## Mounts
-
-Mounts allow containers to have access to the underlying machine, share data between containers and to persist information between **development containers**.
-
-A default mount should be included so that the source code is accessible from inside the container. Source code is stored outside of the container so that a developer's in-flight edits can be extracted, or a new container created in the event a container no longer starts.
-
-While this "workspace mount" is often a "bind" mount, this is not a requirement of this specification. It is also important to note that these mounts may be "bind" mounts that connect to the underlying filesystem and thus cloud environments might not have access to the same data as a local machine.
-
-Inside the container this mount defaults to `/workspace`.
-
-## workspaceFolder and workspaceMount
-
-The default mount point for the source code can be set with the `workspaceMount` property for **image** and **dockerfile** scenarios or using the built in `mounts` property in **Docker Compose** files. This folder should point to the root of a repository (where the `.git` folder is found) so that source control operations work correctly inside the container.
-
-The `workspaceFolder` can then be set to the default folder inside the container that should used in the container. Typically this is either the mount point in the container, or a sub-folder under it. Allowing a sub-folder to be used is particularly important for monorepos given you need the `.git` folder to interact with source control but developers are typically are interacting with a specific sub-project within the overall repository.
-
-See [`workspaceMount` and `workspaceFolder`](devcontainerjson-reference.md#image-or-dockerfile-specific-properties) for reference.
-
-## Users
-
-Users control the permissions of applications executed in the containers, allowing the developer to control them. The specification takes into account two types of user definitions:
-
-* **Container User**: The user that will be used for all operations that run inside a container. This concept is native to containers. It may be set in the container image, using the `containerUser` property for **image** and **dockerfile** scenarios, or using an orchestratric specific property like `user` property in Docker Compose files.
-* **Remote User**: Used to run the [lifecycle](#lifecycle) scripts inside the container. This is also the user tools and editors that connect to the container should use to run their processes. This concept is not native to containers. Set using the `remoteEnv` property in all cases and defaults to the container user.
-
-This separation allows the ENTRYPOINT for the image to execute with different permissions than the developer and allows for developers to switch users without recreating their containers.
-
-# Lifecycle
-
-A development environment goes through different lifecycle events during its use in the outer and inner loop of development.
-
-- Configuration Validation
-- Environment Creation
-- Environment Stop
-- Environment Resume
-
-## Configuration Validation
-
-The exact steps required to validate configuration can vary based on exactly where the **development container** metadata is persisted. However, when considering a `devcontainer.json` file, the following validation should occur:
-
-1. Validate that a workspace source folder has been provided. It is up to the implementing tool to determine what to do if no source folder is provided.
-2. Search for a `devcontainer.json` file in one of the locations [above](#devcontainerjson) in the workspace source folder.
-3. If no `devcontainer.json` is found, it is up to the implementing tool or service to determine what to do. This specification does not dictate this behavior.
-4. Validate that the metadata (for example `devcontainer.json`) contains all parameters required for the selected configuration type.
-
-## Environment Creation
-
-The creation process goes through the steps necesarry to go from the user configuration to a working **environment** that is ready to be used.
-
-### Initialization
-
-During this step, the following is executed:
-- Validate access to the container orchestrator specified by the configuration.
-- Execution of `initializeCommand`.
-
-### Image creation
-
-The first part of environment creation is generating the final image(s) that the **development containers** are going to use. This step is orchestrator dependent and can consist of just pulling a Docker image, running Docker build, or docker-compose build. Additionally, this step is useful on its own since it permits the creation of intermediate images that can be uploaded and used by other users, thus cutting down on creation time. It is encouraged that tools implementing this specification give access to a command that just executes this step.
-
-This step executes the following tasks:
-
-1. [Configuration Validation](#configuration-validation)
-2. Pull/build/execute of the defined container orchestration format to create images.
-3. Validate the result of these operations.
-
-### Container Creation
-
-After image creation, containers are created based on that image and setup.
-
-This step executes the following tasks:
-
-1. [Optional] Perform any required user UID/GID sync'ing (more next)
-2. Create the container(s) based on the properties specified above.
-3. Validate the container(s) were created successfully.
-
-Note that container [mounts](#mounts), [environment variables](#environment-variables), and [user](#users) configuration should be applied at this point. However, remote user and environment variable configuration should **not** be.
-
-UID/GID sync'ing is an optional task for Linux (only) and that executes if the `updateRemoteUserUID` property is set to true and a `containerUser` or `remoteUser` is specified. In this case, an image update should be made prior to creating the container to set the specified user's UID and GID to match the current local user’s UID/GID to avoid permission problems with bind mounts. Implementations **may** skip this task if they do not use bind mounts on Linux, or use a container engine that does this translation automatically.
-
-### Post Container Creation
-
-At the end of the container creation step, a set of commands are executed inside the **main** container:
-- `onCreateCommand`, `updateContentCommand` and `postCreateCommand`. This set of commands is executed in sequence on a container the first time it's created and depending on the creation parameters received. You can learn more in the [documentation on lifecycle scripts](devcontainerjson-reference.md#lifecycle-scripts). By default, `postCreateCommand` is executed in the background after reporting the successful creation of the development environment.
-- If the `waitFor` property is defined, then execution should block until all commands in the sequence up to the specified property have executed. This property defaults to `updateContentCommand`.
-
-Remote [environment variables](#environment-variables) and [user](#users) configuration should be applied to all created processes in the container (inclusive of `userEnvProbe`).
-
-### Implementation specific steps
-
-After these steps have been executed, any implementation specific commands can safely execute. Specifically, any processes required by the implementation to support other properties in this specification should be started at this point. These may occur in parallel to any non-blocking, background post-container creation commands (as dictated by the `waitFor` property).
-
-Any user facing processes should have remote [environment variables](#environment-variables) and [user](#users) configuration applied (inclusive of `userEnvProbe`).
-
-For example, in the [CLI reference implementation](https://github.com/devcontainers/cli), this is the point in which anything executed with `devcontainer exec` would run.
-
-Typically, this is also the step where implementors would apply config or settings from the `customizations` section of the dev container metadata (e.g., VS Code installs extensions based on the `customizations.vscode.extensions` property). Examples of these can be found in the [supporting tools section](supporting-tools.md) reference. However, applying these at this point is not strictly required or mandated by this specification.
-
-Once these final steps have occurred, implementing tools or services may connect to the environment as they see fit.
-
-## Environment Stop
-
-The intention of this step is to ensure all containers are stopped correctly based on the appropriate orchestrator specific steps to ensure no data is lost. It is up to the implementing tool or service to determine when this event should happen.
-
-## Environment Resume
-
-While it is not a strict requirement to keep a **development container** after it has been stopped, this is the most common scenario.
-
-To resume the environment from a stopped state:
-
-1. Restart all related containers.
-2. Follow the appropriate [implementation specific steps](#implementation-specific-steps).
-3. Additionally, execute the `postStartCommand` and `postAttachCommand` in the container.
-
-Like during the create process, remote [environment variables](#environment-variables) and [user](#users) configuration should be applied to all created processes in the container (inclusive of `userEnvProbe`).
-
-## Parallel lifecycle script execution
-
-Dev containers support a single command for each of its lifecycle scripts. While serial execution of multiple commands can be achieved with `;`, `&&`, etc., parallel execution deserves first-class support.
-
-All lifecycle scripts have been extended to support `object` types. The key of the `object` will be a unique name for the command and the value will be the `string` or `array` command. Each command must exit successfully for the stage to be considered successful.
-
-Each entry in the `object` will be run in parallel during that lifecycle step.
-
-### Example
-
-```json
-{
- "postCreateCommand": {
- "server": "npm start",
- "db": ["mysql", "-u", "root", "-p", "my database"]
- }
-}
-```
-
-# Definitions
-
-#### **Project Workspace Folder**
-
-The **project workspace folder** is where an implementing tool should begin to search for `devcontainer.json` files. If the target project on disk is using git, the **project workspace folder** is typically the root of the git repository.
diff --git a/docs/specs/devcontainerjson-reference.md b/docs/specs/devcontainerjson-reference.md
deleted file mode 100644
index 5525c84d..00000000
--- a/docs/specs/devcontainerjson-reference.md
+++ /dev/null
@@ -1,175 +0,0 @@
-# Dev Container metadata reference
-
-The `devcontainer.json` file contains any needed metadata and settings required to configurate a **development container** for a given well-defined tool and runtime stack. It can be used by [tools and services that support the dev container spec](supporting-tools.md) to create a **development environment** that contains one or more **development containers**.
-
-Metadata properties marked with a 🏷️ can be stored in the `devcontainer.metadata` **container image label** in addition to `devcontainer.json`. This label can contain an array of json snippets that will be automatically merged with `devcontainer.json` contents (if any) when a container is created.
-
-## General devcontainer.json properties
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `name` | string | A name for the dev container displayed in the UI |
-| `forwardPorts` 🏷️ | array | An array of port numbers or `"host:port"` values (e.g. `[3000, "db:5432"]`) that should always be forwarded from inside the primary container to the local machine (including on the web). The property is most useful for forwarding ports that cannot be auto-forwarded because the related process that starts before the `devcontainer.json` supporting service / tool connects or for forwarding a service not in the primary container in Docker Compose scenarios (e.g. `"db:5432"`). Defaults to `[]`. |
-| `portsAttributes` 🏷️ | object | Object that maps a port number, `"host:port"` value, range, or regular expression to a set of default options. See [port attributes](#port-attributes) for available options. For example:
`"portsAttributes": {"3000": {"label": "Application port"}}` |
-| `otherPortsAttributes` 🏷️ | object | Default options for ports, port ranges, and hosts that aren't configured using `portsAttributes`. See [port attributes](#port-attributes) for available options. For example:
`"otherPortsAttributes": {"onAutoForward": "silent"}` |
-| `containerEnv` 🏷️ | object | A set of name-value pairs that sets or overrides environment variables for the container. Environment and [pre-defined variables](#variables-in-devcontainerjson) may be referenced in the values. For example:
`"containerEnv": { "MY_VARIABLE": "${localEnv:MY_VARIABLE}" }`
If you want to reference an existing container variable while setting this one (like updating the `PATH`), use `remoteEnv` instead.
`containerEnv` will set the variable on the Docker container itself, so all processes spawned in the container will have access to it. But it will also be static for the life of the container - you must rebuild the container to update the value.
We recommend using `containerEnv` (over `remoteEnv`) as much as possible since it allows all processes to see the variable and isn't client-specific. |
-| `remoteEnv` 🏷️ | object | A set of name-value pairs that sets or overrides environment variables for the `devcontainer.json` supporting service / tool (or sub-processes like terminals) but not the container as a whole. Environment and [pre-defined variables](#variables-in-devcontainerjson) may be referenced in the values.
You may want to use `remoteEnv` (over `containerEnv`) if the value isn't static since you can update its value without having to rebuild the full container. |
-| `remoteUser` 🏷️ | string | Overrides the user that `devcontainer.json` supporting services tools / runs as in the container (along with sub-processes like terminals, tasks, or debugging). Does not change the user the container as a whole runs as which can be set using `containerUser`. Defaults to the user the container as a whole is running as (often `root`).
You may learn more in the [remoteUser section below](#remoteUser). |
-| `containerUser` 🏷️ | string | Overrides the user for all operations run as inside the container. Defaults to either `root` or the last `USER` instruction in the related Dockerfile used to create the image. If you want any connected tools or related processes to use a different user than the one for the container, see `remoteUser`. |
-| `updateRemoteUserUID` 🏷️ | boolean | On Linux, if `containerUser` or `remoteUser` is specified, the user's UID/GID will be updated to match the local user's UID/GID to avoid permission problems with bind mounts. Defaults to `true`. |
-| `userEnvProbe` 🏷️ | enum | Indicates the type of shell to use to "probe" for user environment variables to include in `devcontainer.json` supporting services' / tools' processes: `none`, `interactiveShell`, `loginShell`, or `loginInteractiveShell` (default). The specific shell used is based on the default shell for the user (typically bash). For example, bash interactive shells will typically include variables set in `/etc/bash.bashrc` and `~/.bashrc` while login shells usually include variables from `/etc/profile` and `~/.profile`. Setting this property to `loginInteractiveShell` will get variables from all four files. |
-| `overrideCommand` 🏷️ | boolean | Tells `devcontainer.json` supporting services / tools whether they should run `/bin/sh -c "while sleep 1000; do :; done"` when starting the container instead of the container's default command (since the container can shut down if the default command fails). Set to `false` if the default command must run for the container to function properly. Defaults to `true` for when using an image Dockerfile and `false` when referencing a Docker Compose file. |
-| `shutdownAction` 🏷️ | enum | Indicates whether `devcontainer.json` supporting tools should stop the containers when the related tool window is closed / shut down.
Values are `none`, `stopContainer` (default for image or Dockerfile), and `stopCompose` (default for Docker Compose). |
-| `init` 🏷️ | boolean | Defaults to `false`. Cross-orchestrator way to indicate whether the [tini init process](https://github.com/krallin/tini) should be used to help deal with zombie processes. |
-| `privileged` 🏷️ | boolean | Defaults to `false`. Cross-orchestrator way to cause the container to run in privileged mode (`--privileged`). Required for things like Docker-in-Docker, but has security implications particularly when running directly on Linux. |
-| `capAdd` 🏷️ | array | Defaults to `[]`. Cross-orchestrator way to add capabilities typically disabled for a container. Most often used to add the `ptrace` capability required to debug languages like C++, Go, and Rust. For example:
`"capAdd": ["SYS_PTRACE"]` |
-| `securityOpt` 🏷️ | array | Defaults to `[]`. Cross-orchestrator way to set container security options. For example:
`"securityOpt": [ "seccomp=unconfined" ]` |
-| `mounts` 🏷️ | string or object | Defaults to unset. Cross-orchestrator way to add additional mounts to a container. Each value is a string that accepts the same values as the [Docker CLI `--mount` flag](https://docs.docker.com/engine/reference/commandline/run/#mount). Environment and [pre-defined variables](#variables-in-devcontainerjson) may be referenced in the value. For example:
`"mounts": [{ "source": "dind-var-lib-docker", "target": "/var/lib/docker", "type": "volume" }]` |
-| `features` | object | An object of [Dev Container Feature IDs](https://containers.dev/features) and related options to be added into your primary container. The specific options that are available varies by feature, so see its documentation for additional details. For example:
`"features": { "ghcr.io/devcontainers/features/github-cli": {} }` |
-| `overrideFeatureInstallOrder` | array | By default, Features will attempt to automatically set the order they are installed based on a `installsAfter` property within each of them. This property allows you to override the Feature install order when needed. For example:
`"overrideFeatureInstallorder": [ "ghcr.io/devcontainers/features/common-utils", "ghcr.io/devcontainers/features/github-cli" ]` |
-| `customizations` 🏷️| object | Product specific properties, defined in [supporting tools](supporting-tools.md) |
-
-## Scenario specific properties
-
-The focus of `devcontainer.json` is to describe how to enrich a container for the purposes of development rather than acting as a multi-container orchestrator format. Instead, container orchestrator formats can be referenced when needed to manage multiple containers and their lifecycles. Today, `devcontainer.json` includes scenario specific properties for working without a container orchestrator (by directly referencing an image or Dockerfile) and for using Docker Compose as a simple multi-container orchestrator.
-
-### Image or Dockerfile specific properties
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `image` | string | **Required** when using an image. The name of an image in a container registry ([DockerHub](https://hub.docker.com), [GitHub Container Registry](https://docs.github.com/packages/guides/about-github-container-registry), [Azure Container Registry](https://azure.microsoft.com/services/container-registry/)) that `devcontainer.json` supporting services / tools should use to create the dev container. |
-| `build.dockerfile` | string |**Required** when using a Dockerfile. The location of a [Dockerfile](https://docs.docker.com/engine/reference/builder/) that defines the contents of the container. The path is relative to the `devcontainer.json` file. |
-| `build.context` | string | Path that the Docker build should be run from relative to `devcontainer.json`. For example, a value of `".."` would allow you to reference content in sibling directories. Defaults to `"."`. |
-| `build.args` | Object | A set of name-value pairs containing [Docker image build arguments](https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables---build-arg) that should be passed when building a Dockerfile. Environment and [pre-defined variables](#variables-in-devcontainerjson) may be referenced in the values. Defaults to not set. For example: `"build": { "args": { "MYARG": "MYVALUE", "MYARGFROMENVVAR": "${localEnv:VARIABLE_NAME}" } }` |
-| `build.target` | string | A string that specifies a [Docker image build target](https://docs.docker.com/engine/reference/commandline/build/#specifying-target-build-stage---target) that should be passed when building a Dockerfile. Defaults to not set. For example: `"build": { "target": "development" }` |
-| `build.cacheFrom` | string,
array | A string or array of strings that specify one or more images to use as caches when building the image. Cached image identifiers are passed to the `docker build` command with `--cache-from`. |
-| `appPort` | integer,
string,
array | In most cases, we recommend using the new [forwardPorts property](#general-devcontainerjson-properties). This property accepts a port or array of ports that should be published locally when the container is running.Unlike `forwardPorts`, your application may need to listen on all interfaces (`0.0.0.0`) not just `localhost` for it to be available externally. Defaults to `[]`.
Learn more about publishing vs forwarding ports [here](#publishing-vs-forwarding-ports).
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array properties. |
-| `workspaceMount` | string | Requires `workspaceFolder` be set as well. Overrides the default local mount point for the workspace when the container is created. Supports the same values as the [Docker CLI `--mount` flag](https://docs.docker.com/engine/reference/commandline/run/#add-bind-mounts-or-volumes-using-the---mount-flag). Environment and [pre-defined variables](#variables-in-devcontainerjson) may be referenced in the value. For example:
`"workspaceMount": "source=${localWorkspaceFolder}/sub-folder,target=/workspace,type=bind,consistency=cached", "workspaceFolder": "/workspace"` |
-| `workspaceFolder` | string | Requires `workspaceMount` be set. Sets the default path that `devcontainer.json` supporting services / tools should open when connecting to the container. Defaults to the automatic source code mount location. |
-| `runArgs` | array | An array of [Docker CLI arguments](https://docs.docker.com/engine/reference/commandline/run/) that should be used when running the container. Defaults to `[]`. For example, this allows ptrace based debuggers like C++ to work in the container:
`"runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ]` . |
-
-### Docker Compose specific properties
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `dockerComposeFile` | string,
array | **Required** when [using Docker Compose](https://docs.docker.com/compose/). Path or an ordered list of paths to Docker Compose files relative to the `devcontainer.json` file. Using an array is useful [when extending your Docker Compose configuration](https://docs.docker.com/compose/extends/#multiple-compose-files). The order of the array matters since the contents of later files can override values set in previous ones.
The default `.env` file is picked up from the root of the project, but you can use `env_file` in your Docker Compose file to specify an alternate location.
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array properties. |
-| `service` | string | **Required** when [using Docker Compose](https://docs.docker.com/compose/). The name of the service `devcontainer.json` supporting services / tools should connect to once running. |
-| `runServices` | array | An array of services in your Docker Compose configuration that should be started by `devcontainer.json` supporting services / tools. These will also be stopped when you disconnect unless `"shutdownAction"` is `"none"`. Defaults to all services. |
-| `workspaceFolder` | string | Sets the default path that `devcontainer.json` supporting services / tools should open when connecting to the container (which is often the path to a volume mount where the source code can be found in the container). Defaults to `"/"`. |
-
-## Tool-specific properties
-
-While most properties apply to any `devcontainer.json` supporting tool or service, a few are specific to certain tools. You may explore this in the [supporting tools and services document](supporting-tools.md).
-
-## Lifecycle scripts
-
-When creating or working with a dev container, you may need different commands to be run at different points in the container's lifecycle. The table below lists a set of command properties you can use to update what the container's contents in the order in which they are run (for example, `onCreateCommand` will run after `initializeCommand`). Each command property is an string or list of command arguments that should execute from the `workspaceFolder`.
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `initializeCommand` | string,
array,
object | A command string or list of command arguments to run on the **host machine** before the container is created.
⚠️ The command is run wherever the source code is located on the host. For cloud services, this is in the cloud.
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array vs object properties. |
-| `onCreateCommand` 🏷️ | string,
array,
object | This command is the first of three (along with `updateContentCommand` and `postCreateCommand`) that finalizes container setup when a dev container is created. It and subsequent commands execute **inside** the container immediately after it has started for the first time.
Cloud services can use this command when caching or prebuilding a container. This means that it will not typically have access to user-scoped assets or secrets.
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array vs object properties. |
-| `updateContentCommand` 🏷️ | string,
array,
object | This command is the second of three that finalizes container setup when a dev container is created. It executes inside the container after `onCreateCommand` whenever new content is available in the source tree during the creation process.
It will execute at least once, but cloud services will also periodically execute the command to refresh cached or prebuilt containers. Like cloud services using `onCreateCommand`, it can only take advantage of repository and org scoped secrets or permissions.
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array vs object properties. |
-| `postCreateCommand` 🏷️ | string,
array,
object | This command is the last of three that finalizes container setup when a dev container is created. It happens after `updateContentCommand` and once the dev container has been assigned to a user for the first time.
Cloud services can use this command to take advantage of user specific secrets and permissions.
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array vs object properties. |
-| `postStartCommand` 🏷️ | string,
array,
object | A command to run each time the container is successfully started.
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array vs object properties. |
-| `postAttachCommand` 🏷️ | string,
array,
object | A command to run each time a tool has successfully attached to the container.
Note that the array syntax will execute the command without a shell. You can [learn more](#formatting-string-vs-array-properties) about formatting string vs array vs object properties. |
-| `waitFor` 🏷️ | enum | An enum that specifies the command any tool should wait for before connecting. Defaults to `updateContentCommand`. This allows you to use `onCreateCommand` or `updateContentCommand` for steps that must happen before `devcontainer.json` supporting tools connect while still using `postCreateCommand` for steps that can happen behind the scenes afterwards. |
-
-For each command property, if the value is a single string, it will be run in `/bin/sh`. Use `&&` in a string to execute multiple commands. For example, `"yarn install"` or `"apt-get update && apt-get install -y curl"`. The array syntax `["yarn", "install"]` will invoke the command (in this case `yarn`) directly without using a shell. Each fires after your source code has been mounted, so you can also run shell scripts from your source tree. For example: `bash scripts/install-dev-tools.sh`
-
-If one of the lifecycle scripts fails, any subsequent scripts will not be executed. For instance, if `postCreateCommand` fails, `postStartCommand` and any following scripts will be skipped.
-
-## Minimum host requirements
-
-While `devcontainer.json` does not focus on hardware or VM provisioning, it can be useful to know your container's minimum RAM, CPU, and storage requirements. This is what the `hostRequirements` properties allow you to do. Cloud services can use these properties to automatically default to the best compute option available, while in other cases, you will be presented with a warning if the requirements are not met.
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `hostRequirements.cpus` 🏷️ | integer | Indicates the minimum required number of CPUs / virtual CPUs / cores. For example: `"hostRequirements": {"cpus": 2}` |
-| `hostRequirements.memory` 🏷️ | string | A string indicating minimum memory requirements with a `tb`, `gb`, `mb`, or `kb` suffix. For example, `"hostRequirements": {"memory": "4gb"}` |
-| `hostRequirements.storage` 🏷️ | string | A string indicating minimum storage requirements with a `tb`, `gb`, `mb`, or `kb` suffix. For example, `"hostRequirements": {"storage": "32gb"}` |
-
-## Port attributes
-
-The `portsAttributes` and `otherPortsAttributes` properties allow you to map default port options for one or more manually or automatically forwarded ports. The following is a list of options that can be set in the configuration object assigned to the property.
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `label` 🏷️ | string | Display name for the port in the ports view. Defaults to not set. |
-| `protocol` 🏷️ | enum | Controls protocol handling for forwarded ports. When not set, the port is assumed to be a raw TCP stream which, if forwarded to `localhost`, supports any number of protocols. However, if the port is forwarded to a web URL (e.g. from a cloud service on the web), only HTTP ports in the container are supported. Setting this property to `https` alters handling by ignoring any SSL/TLS certificates present when communicating on the port and using the correct certificate for the forwarded URL instead (e.g `https://*.githubpreview.dev`). If set to `http`, processing is the same as if the protocol is not set. Defaults to not set. |
-| `onAutoForward` 🏷️ | enum | Controls what should happen when a port is auto-forwarded once you've connected to the container. `notify` is the default, and a notification will appear when the port is auto-forwarded. If set to `openBrowser`, the port will be opened in the system's default browser. A value of `openBrowserOnce` will open the browser only once. `openPreview` will open the URL in `devcontainer.json` supporting services' / tools' embedded preview browser. A value of `silent` will forward the port, but take no further action. A value of `ignore` means that this port should not be auto-forwarded at all. |
-| `requireLocalPort` 🏷️ | boolean | Dictates when port forwarding is required to map the port in the container to the same port locally or not. If set to `false`, the `devcontainer.json` supporting services / tools will attempt to use the specified port forward to `localhost`, and silently map to a different one if it is unavailable. If set to `true`, you will be notified if it is not possible to use the same port. Defaults to `false`. |
-| `elevateIfNeeded` 🏷️ | boolean | Forwarding low ports like 22, 80, or 443 to `localhost` on the same port from `devcontainer.json` supporting services / tools may require elevated permissions on certain operating systems. Setting this property to `true` will automatically try to elevate the `devcontainer.json` supporting tool's permissions in this situation. Defaults to `false`. |
-
-## Formatting string vs. array properties
-
-The format of certain properties will vary depending on the involvement of a shell.
-
-`postCreateCommand`, `postStartCommand`, `postAttachCommand`, and `initializeCommand` all have 3 types:
-* Array: Passed to the OS for execution without going through a shell
-* String: Goes through a shell (it needs to be parsed into command and arguments)
-* Object: All lifecycle scripts have been extended to support `object` types to allow for [parallel execution](../specs/devcontainer-reference.md/#parallel-lifecycle-script-execution)
-
-`runArgs` only has the array type. Using `runArgs` via a typical command line, you'll need single quotes if the shell runs into parameters with spaces. However, these single quotes aren't passed on to the executable. Thus, in your `devcontainer.json`, you'd follow the array format and leave out the single quotes:
-
-```json
-"runArgs": ["--device-cgroup-rule=my rule here"]
-```
-
-Rather than:
-
-```json
-"runArgs": ["--device-cgroup-rule='my rule here'"]
-```
-
-We can compare the string, array, and object versions of `postAttachCommand` as well. You can use the following string format, which will remove the single quotes as part of the shell's parsing:
-
-```json
-"postAttachCommand": "echo foo='bar'"
-```
-
-By contrast, the array format will keep the single quotes and write them to standard out (you can see the output in the dev container log):
-
-```json
-"postAttachCommand": ["echo", "foo='bar'"]
-```
-
-Finally, you may use an object format:
-
-```json
-{
- "postAttachCommand": {
- "server": "npm start",
- "db": ["mysql", "-u", "root", "-p", "my database"]
- }
-}
-```
-
-## Variables in devcontainer.json
-
-Variables can be referenced in certain string values in `devcontainer.json` in the following format: **${variableName}**. The following is a list of available variables you can use.
-
-| Variable | Properties | Description |
-|----------|---------|----------------------|
-| `${localEnv:VARIABLE_NAME}` | Any | Value of an environment variable on the **host machine** (in this case, called `VARIABLE_NAME`). Unset variables are left blank. For example, this would set a variable to your local home folder on Linux / macOS or the user folder on Windows:
`"remoteEnv": { "LOCAL_USER_PATH": "${localEnv:HOME}${localEnv:USERPROFILE}" }`
A default value for when the environment variable is not set can be given with `${localEnv:VARIABLE_NAME:default_value}`.
⚠️ For a cloud service, the host is in the cloud rather than your local machine.|
-| `${containerEnv:VARIABLE_NAME}` | `remoteEnv` | Value of an existing environment variable inside the container once it is up and running (in this case, called `VARIABLE_NAME`). For example:
`"remoteEnv": { "PATH": "${containerEnv:PATH}:/some/other/path" }`
A default value for when the environment variable is not set can be given with `${containerEnv:VARIABLE_NAME:default_value}`. |
-| `${localWorkspaceFolder}` | Any | Path of the local folder that was opened in the `devcontainer.json` supporting service / tool (that contains `.devcontainer/devcontainer.json`). |
-| `${containerWorkspaceFolder}` | Any | The path that the workspaces files can be found in the container. |
-| `${localWorkspaceFolderBasename}` | Any | Name of the local folder that was opened in the `devcontainer.json` supporting service / tool (that contains `.devcontainer/devcontainer.json`). |
-| `${containerWorkspaceFolderBasename}` | Any | Name of the folder where the workspace files can be found in the container. |
-| `${devcontainerId}` | Any | Allow features to refer to an identifier that is unique to the dev container they are installed into and that is stable across rebuilds.
The properties supporting it in devcontainer.json are: `name`, `runArgs`, `initializeCommand`, `onCreateCommand`, `updateContentCommand`, `postCreateCommand`, `postStartCommand`, `postAttachCommand`, `workspaceFolder`, `workspaceMount`, `mounts`, `containerEnv`, `remoteEnv`, `containerUser`, `remoteUser`, and `customizations`. |
-
-## Schema
-
-You can see the dev container schema [here](https://github.com/devcontainers/spec/blob/main/schemas/devContainer.base.schema.json).
-
-
-## Publishing vs forwarding ports
-
-Docker has the concept of "publishing" ports when the container is created. Published ports behave very much like ports you make available to your local network. If your application only accepts calls from `localhost`, it will reject connections from published ports just as your local machine would for network calls. Forwarded ports, on the other hand, actually look like `localhost` to the application.
-
-## remoteUser
-
-A dev container configuration will inherit the `remoteUser` property from the base image it uses.
-
-Using the [images](https://github.com/devcontainers/images) and [Templates](https://github.com/devcontainers/templates) part of the spec as an example: `remoteUser` in these images is set to a custom value - you may view an example in the [C++ image](https://github.com/devcontainers/images/blob/main/src/cpp/.devcontainer/devcontainer.json#L26). The [C++ Template](https://github.com/devcontainers/templates/tree/main/src/cpp) will then inherit the custom `remoteUser` value from [its base C++ image](https://github.com/devcontainers/templates/blob/main/src/cpp/.devcontainer/Dockerfile#L1).
diff --git a/docs/specs/supporting-tools.md b/docs/specs/supporting-tools.md
deleted file mode 100644
index d069e0d5..00000000
--- a/docs/specs/supporting-tools.md
+++ /dev/null
@@ -1,135 +0,0 @@
-# Supporting tools and services
-
-This page outlines tools and services that currently support the development container specification, including the `devcontainer.json` format. A `devcontainer.json` file in your project tells tools and services that support the dev container spec how to access (or create) a dev container with a well-defined tool and runtime stack.
-
-While most [dev container properties](devcontainerjson-reference.md) apply to any supporting tool or service, a few are specific to certain tools, which are outlined below.
-
-## Editors
-
-### Visual Studio Code
-
-Visual studio code specific properties go under `vscode` inside `customizations`.
-
-
-```jsonc
-"customizations": {
- // Configure properties specific to VS Code.
- "vscode": {
- // Set *default* container specific settings.json values on container create.
- "settings": {},
- "extensions": [],
- }
-}
-```
-
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `extensions` | array | An array of extension IDs that specify the extensions that should be installed inside the container when it is created. Defaults to `[]`. |
-| `settings` | object | Adds default `settings.json` values into a container/machine specific settings file. Defaults to `{}`. |
-
-Please note that [Dev Containers](#visual-studio-code-remote---containers) and [GitHub Codespaces](#github-codespaces) support the VS Code properties.
-
-### Visual Studio
-
-Visual Studio added Dev Container support in Visual Studio 2022 17.4 for C++ projects using CMake Presets. It is part of the Linux and embedded development with C++ workload, so make sure it is selected in your VS installation. Visual Studio manages the lifecycle of Dev Containers it uses as you work, but it treats them as remote targets in a similar way to other Linux or WSL targets.
-
-You may learn more in the [announcement blog post](https://devblogs.microsoft.com/cppblog/dev-containers-for-c-in-visual-studio/).
-
-## Tools
-
-### Dev Container CLI
-
-A dev container command line interface (CLI) that implements this specification. It is in development in the [devcontainers/cli](https://github.com/devcontainers/cli) repo.
-
-### VS Code extension CLI
-
-VS Code has a [CLI](https://code.visualstudio.com/docs/remote/devcontainer-cli) which may be installed within the Dev Containers extension or through the command line.
-
-### Cachix devenv
-
-Cachix's [devenv](https://devenv.sh/) supports automatically generating a `.devcontainer.json` file so you can use it with any Dev Container spec supporting tool. See [devenv documentation](https://devenv.sh/integrations/codespaces-devcontainer/) for detais.
-
-### Jetpack.io Devbox
-
-[Jetpack.io's VS Code extension](https://marketplace.visualstudio.com/items?itemName=jetpack-io.devbox) supports a **Generate Dev Container files** command so you can use Jetpack.io from Dev Container spec supporting tools.
-
-### Visual Studio Code Dev Containers
-
-The [**Visual Studio Code Dev Containers** extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) lets you use a container as a full-featured development environment. It allows you to open any folder inside (or mounted into) a container and take advantage of Visual Studio Code's full feature set. There is more information in the Dev Containers [documentation](https://code.visualstudio.com/docs/remote/containers).
-
-> **Tip:** If you've already built a container and connected to it, be sure to run **Dev Containers: Rebuild Container** from the Command Palette (`kbstyle(F1)`) to pick up any changes you make.
-
-#### Product specific properties
-
-Dev Containers implements the [VS Code properties](#visual-studio-code) specific properties.
-
-#### Product specific limitations
-
-Some properties may also have certain limitations in the Dev Containers extension.
-
-| Property or variable | Type | Description |
-|----------|------|-------------|
-| `workspaceMount` | string | Not yet supported when using Clone Repository in Container Volume. |
-| `workspaceFolder` | string | Not yet supported when using Clone Repository in Container Volume. |
-| `${localWorkspaceFolder}` | Any | Not yet supported when using Clone Repository in Container Volume. |
-| `${localWorkspaceFolderBasename}` | Any | Not yet supported when using Clone Repository in Container Volume. |
-
-### GitHub Codespaces
-
-A [codespace](https://docs.github.com/en/codespaces/overview) is a development environment that's hosted in the cloud. Codespaces run on a variety of VM-based compute options hosted by GitHub.com, which you can configure from 2 core machines up to 32 core machines. You can connect to your codespaces from the browser or locally using Visual Studio Code.
-
-> **Tip:** If you've already built a codespace and connected to it, be sure to run **Codespaces: Rebuild Container** from the Command Palette (`kbstyle(F1)`) to pick up any changes you make.
-
-> **Tip** Codespaces implements an auto `workspaceFolder` mount in **Docker Compose** scenarios.
-
-#### Product specific properties
-GitHub Codespaces works with a growing number of tools and, where applicable, their `devcontainer.json` properties. For example, connecting the Codespaces web editor or VS Code enables the use of [VS Code properties](#visual-studio-code).
-
-If your Codespaces project needs additional permissions for other repositories, you can configure this through the `repositories` and `permissions` properties. You may learn more about this in the [Codespaces documentation](https://docs.github.com/en/codespaces/managing-your-codespaces/managing-repository-access-for-your-codespaces). As with other tools, Codespaces specific properties are placed within a `codespaces` namespace inside the `customizations` property.
-
-```jsonc
-"customizations": {
- // Configure properties specific to Codespaces.
- "codespaces": {
- "repositories": {
- "my_org/my_repo": {
- "permissions": {
- "issues": "write"
- }
- }
- }
- }
-}
-```
-
-You can customize which files are initially opened when the codespace is created:
-```jsonc
-"customizations": {
- // Configure properties specific to Codespaces.
- "codespaces": {
- "openFiles": [
- "README"
- "src/index.js"
- ]
- }
-}
-```
-
-The paths are relative to the root of the repository. They will be opened in order, with the first file activated.
-
-Note that currently Codespaces reads these properties from devcontainer.json, not image metadata.
-
-#### Product specific limitations
-
-Some properties may apply differently to Codespaces.
-
-| Property or variable | Type | Description |
-|----------|---------|----------------------|
-| `mounts` | array | Codespaces ignores "bind" mounts with the exception of the Docker socket. Volume mounts are still allowed.|
-| `forwardPorts` | array | Codespaces does not yet support the `"host:port"` variation of this property. |
-| `portsAttributes` | object | Codespaces does not yet support the `"host:port"` variation of this property.|
-| `shutdownAction` | enum | Does not apply to Codespaces. |
-| `${localEnv:VARIABLE_NAME}` | Any | For Codespaces, the host is in the cloud rather than your local machine.|
-| `customizations.codespaces` | object | Codespaces reads this property from devcontainer.json, not image metadata. |
-| `hostRequirements` | object | Codespaces reads this property from devcontainer.json, not image metadata. |
diff --git a/images/dev-container-stages.png b/images/dev-container-stages.png
deleted file mode 100644
index b4b1d774..00000000
Binary files a/images/dev-container-stages.png and /dev/null differ
diff --git a/index.bs b/index.bs
new file mode 100644
index 00000000..d0cdec4a
--- /dev/null
+++ b/index.bs
@@ -0,0 +1,476 @@
+
+Title: Development Containers
+Abstract: A Development Container (or Dev Container for short) allows you to use a container as a full-featured development environment. It can be used to run an application, to separate tools, libraries, or runtimes needed for working with a codebase, and to aid in continuous integration and testing. Dev containers can be run locally or remotely, in a private or public cloud, in a variety of supporting tools and editors.
+Status: LD
+Warning: Not Ready
+Shortname: devcontainers
+Repository: devcontainers-community/devcontainers.org
+Favicon: https://avatars.githubusercontent.com/u/102692984?s=200&v=4
+URL: https://devcontainers.org/spec/
+Editor: Samruddhi Khandale, Microsoft, https://github.com/samruddhikhandale
+Editor: Brigit Murtaugh, Microsoft, https://github.com/bamurtaugh
+Editor: Josh Spicer, Microsoft, https://github.com/joshspicer
+Former Editor: Edmundo Gonzalez, Microsoft, https://github.com/edgonmsft
+!Participate: Participate on GitHub!
+Markup Shorthands: markdown yes
+Complain About: accidental-2119 no, missing-example-ids no
+Boilerplate: omit conformance
+
+
+
+
+
+
+# Introduction # {#intro}
+
+The purpose of the [=development container specification=] is to provide a way to enrich containers with the content and metadata necessary to enable development inside them. These container [=environments=] should be easy to use, create, and recreate.
+
+A development container is a container in which a user can develop an application. Tools that want to implement this specification should provide a set of features/commands that give more flexibility to users and allow [=development containers=] to scale to large development groups.
+
+An environment is defined as a logical instance of one or more [=development containers=], along with any needed side-car containers. An environment is based on one set of metadata that can be managed as a single unit. Users can create multiple [=environments=] from the same configuration metadata for different purposes.
+
+[=Development containers=] allow one to define a repeatable development environment for a user or team of developers that includes the execution environment the application needs. A development container defines an environment in which you develop your application before you are ready to deploy. While deployment and development containers may resemble one another, you may not want to include tools in a deployment image that you use during development and you may need to use different secrets or other settings.
+
+Furthermore, working inside a development container can require additional metadata to drive tooling or service experiences than you would normally need with a production container. Providing a structured and consistent form for this metadata is a core part of this specification.
+
+## Lifecycle
+
+A development environment goes through different lifecycle events during its use in the outer and inner loop of development.
+
+1. Configuration Validation
+2. Environment Creation
+3. Environment Stop
+4. Environment Resume
+
+### Configuration validation
+
+The exact steps required to validate a configuration can vary based on exactly where the development container metadata is persisted. However, when considering a [=devcontainer.json=] file, the following validation should occur:
+
+1. Validate that a workspace source folder has been provided. It is up to the implementing tool to determine what to do if no source folder is provided.
+2. [=Search for a devcontainer.json=] in the workspace source folder.
+3. If no [=devcontainer.json=] is found, it is up to the implementing tool or service to determine what to do. This specification does not dictate this behavior.
+4. Validate that the metadata contains all parameters required for the selected configuration type.
+
+
+
+# Configuration # {#config}
+
+There are three primary sources that dev container configuration can come from:
+
+1. devcontainer.json
+2. Docker image metadata
+3. Included dev container features
+
+## devcontainer.json
+
+To search for a devcontainer.json, an agent should look in any of these locations to locate a [=devcontainer.json=]
+
+- `.devcontainer/devcontainer.json`
+- `.devcontainer.json`
+- .devcontainer/$FOLDER/devcontainer.json (where `$FOLDER` is a sub-folder, one level deep)
+
+It is valid that these files may exist in more than one location, so consider providing a mechanism for users to select one when appropriate.
+
+The `devcontainer.json` file is a [JSON-with-comments](https://github.com/microsoft/node-jsonc-parser) file that conforms to the {{DevcontainerJSON}} IDL definition below:
+
+
+dictionary DevcontainerJSON {
+ DOMString name;
+ sequence forwardPorts;
+ any portsAttributes;
+ any otherPortsAttributes;
+ any containerEnv;
+ any remoteEnv;
+ DOMString remoteUser;
+ DOMString containerUser;
+ boolean updateRemoteUserUID;
+ any userEnvProbe;
+ DOMString workspaceFolder;
+};
+
+
+- {{DevcontainerJSON/name}}: A name for the dev container displayed in the UI
+
+- {{forwardPorts}}: An array of port numbers or `"host:port"` values that should always be forwarded from inside the primary container to the local machine (including on the web). Defaults to `[]`.
+
+
+ {
+ // The "db" hostname in docker-compose.yml
+ "forwardPorts": [3000, "db:8080"]
+ }
+
+
+ This property is most useful for forwarding ports that cannot be auto-forwarded because the related process that starts before the [=devcontainer.json=] supporting service/tool connects or for forwarding a service not in the primary container in Docker Compose scenarios.
+
+- {{portsAttributes}}: Object that maps a port number, "host:port" value, range, or regular expression to a set of default options. See port attributes for available options.
+
+
+ {
+ "forwardPorts": [3000],
+ "portsAttributes": {
+ "3000": {
+ "label": "Application port"
+ }
+ }
+ }
+
+
+- {{otherPortsAttributes}}: Default options for ports, port ranges, and hosts that aren't configured using portsAttributes. See port attributes for available options.
+
+
+ {
+ "forwardPorts": [3000],
+ "otherPortsAttributes": {
+ "onAutoForward": "silent"
+ }
+ }
+
+
+- {{containerEnv}}: A set of name-value pairs that sets or overrides environment variables for the container. Environment and pre-defined variables may be referenced in the values.
+
+
+ {
+ "containerEnv": {
+ "MY_VARIABLE": "${localEnv:MY_VARIABLE}"
+ }
+ }
+
+
+
+ If you want to reference an existing container variable while setting this one (like updating the `PATH`), use {{remoteEnv}} instead. {{containerEnv}} will set the variable on the Docker container itself, so all processes spawned in the container will have access to it. But it will also be static for the life of the container - you must rebuild the container to update the value.
+
+ We recommend using containerEnv (over {{remoteEnv}}) as much as possible since it allows all processes to see the variable and isn't client-specific.
+
+
+- {{workspaceFolder}}: Sets the default path that devcontainer.json supporting services/tools should open when connecting to the container. Defaults to the automatic source code mount location.
+
+A core principle of this specification is to seek to enrich existing container orchestrator formats with development container metadata where appropriate rather than replacing them. As a result, the metadata schema includes a set of optional properties for interoperating with different orchestrators. Today, the specification includes scenario-specific properties for working without a container orchestrator (by directly referencing an image or Dockerfile) and for using Docker Compose as a simple multi-container orchestrator. At the same time, this specification leaves space for further development and implementation of other orchestrator mechanisms and file formats.
+
+### Image based
+
+Image based configurations only reference an image that should be reachable and downloadable through docker pull commands. Logins and tokens required for these operations are execution environment specific. The only required parameter is image.
+
+
+partial dictionary DevcontainerJSON {
+ DOMString image;
+};
+
+
+- {{image}}: The name of an image in a container registry (DockerHub, GitHub Container Registry, Azure Container Registry) that devcontainer.json supporting services/tools should use to create the dev container. Required when using an image.
+
+Both [[#image-based]] and [[#dockerfile-based]] configurations share these properties:
+
+
+partial dictionary DevcontainerJSON {
+ // image;
+ // build;
+ (long or DOMString or sequence<(long or DOMString)>) appPort;
+ DevcontainerWorkspaceMount workspaceMount;
+ DevcontainerRunArgs runArgs;
+};
+
+
+- {{image}}: The name of an image in a container registry (DockerHub, GitHub Container Registry, Azure Container Registry) that devcontainer.json supporting services/tools should use to create the dev container. Required when using an image.
+
+- {{build}}: Configuration for building a Dockerfile.
+
+ - {{dockerfile}}: The location of a Dockerfile that defines the contents of the container. Required when using a Dockerfile.
+
+ - {{context}}: Path that the Docker build should be run from relative to devcontainer.json. Defaults to ".".
+
+ - {{args}}: A set of name-value pairs containing Docker image build arguments that should be passed when building a Dockerfile. Defaults to not set.
+
+ - {{target}}: A string that specifies a Docker image build target that should be passed when building a Dockerfile. Defaults to not set.
+
+ - {{cacheFrom}}: A string or array of strings that specify one or more images to use as caches when building the image. Cached image identifiers are passed to the docker build command with --cache-from.
+
+- {{appPort}}: In most cases, we recommend using the new forwardPorts property. This property accepts a port or array of ports that should be published locally when the container is running. Defaults to [].
+
+- {{workspaceMount}}: Overrides the default local mount point for the workspace when the container is created. Supports the same values as the Docker CLI --mount flag.
+
+- {{runArgs}}: An array of Docker CLI arguments that should be used when running the container. Defaults to []. Allows customization for running the container.
+
+### Dockerfile based
+
+
+partial dictionary DevcontainerJSON {
+ BuildOptions build;
+};
+
+
+These configurations are defined as using a Dockerfile to define the starting point of the development containers. As with image based configurations, it is assumed that any base images are already reachable by Docker when performing a docker build command. The only required parameter in this case is the relative reference to the Dockerfile in build.dockerfile.
+
+There are multiple properties that allow users to control how docker build works:
+
+
+dictionary BuildOptions {
+ required DOMString dockerfile;
+ DOMString context;
+ object args;
+ DOMString target;
+ (DOMString or sequence) cacheFrom;
+};
+
+
+### Docker Compose based
+
+
+partial dictionary DevcontainerJSON {
+ (DOMString or sequence) dockerComposeFile;
+ DOMString service;
+ sequence runServices;
+ // Also has workspaceFolder just like "image" and "dockerFile"
+ // DOMString workspaceFolder;
+};
+
+
+Docker Compose configurations use docker-compose (which may be Docker Compose V1 or aliased Docker Compose V2) to create and manage a set of containers required for an application. As with the other configurations, any images required for this operation are assumed to be reachable. The required parameters are:
+
+- {{dockerComposeFile}}: the reference to the Docker Compose file(s) to be used.
+
+- {{service}}: declares the main container that will be used for all other operations. Tools are assumed to also use this parameter to connect to the development container, although they can provide facilities to connect to the other containers as required by the user.
+
+- {{runServices}}: an optional property that indicates the set of services in the docker-compose configuration that should be started or stopped with the environment.
+
+It is important to note that image and dockerfile properties are not needed since Docker Compose supports them natively in the format.
+
+## Docker image metadata
+
+A subset of dev container config options may be stored in the [=devcontainer.metadata=] label on the Docker image that is being used as the base image. The `devcontainer.metadata` is a JSON-encoded string of the following subset of the properties configurable via [=devcontainer.json=].
+
+
+typedef (
+ DevcontainerMetadataItem
+ or sequence
+) DevcontainerMetadata;
+
+dictionary DevcontainerMetadataItem {};
+
+
+The merge logic to combine these properties with [=devcontainer-feature.json=] the
+[=devcontainer.json=] is described in [[#config-merge]].
+
+
+FROM ubuntu:latest
+LABEL "devcontainer.metadata"='[{ "customizations": { "vscode": { ... } } }]'
+
+
+
+
+## Merge dev container configurations ## {#config-merge}
+
+To merge dev container configurations, perform the following described logic for each key to produce a single resulting object. Any properties not listed or excess properties from the source object should not be merged into the final configuration.
+
+- {{init}}: `true` if at least one is `true`, otherwise `false`.
+
+- {{privileged}}: `true` if at least one is `true`, otherwise `false`.
+
+- {{capAdd}}: Union of all `capAdd` arrays without duplicates.
+
+- {{securityOpt}}: Union of all securityOpt arrays without duplicates.
+
+Check [=devcontainer.json=], [=devcontainer-feature.json=], and [=devcontainer.metadata=] if you're wondering which properties are allowed from which sources. For instance [=devcontainer.json=] may specify {{forwardPorts}}, but [=devcontainer-feature.json=] may not.
+
+
+```json
+// devcontainer.json
+{
+ "dockerFile": "./Dockerfile",
+ "customizations": {
+ "vscode": {
+ "settings": {
+ "editor.minimap.enabled": true
+ }
+ }
+ }
+}
+```
+
+```Dockerfile
+FROM ubuntu:latest
+LABEL "devcontainer.metadata"='{ "privileged": true }'
+```
+
+Merging those two dev container configuration sources will result in:
+
+```json
+{
+ "customizations": {
+ "vscode": {
+ "settings": {
+ "editor.minimap.enabled": true
+ }
+ }
+ },
+ "privileged": true
+}
+```
+
+
+
+
+# Dev container features # {#features}
+
+Development container Features are self-contained, shareable units of installation code and development container configuration. The name comes from the idea that referencing one of them allows you to quickly and easily add more tooling, runtime, or library “Features” into your development container for you or your collaborators to use.
+
+Feature metadata is captured by a [=devcontainer-feature.json=] file in the root folder of the feature.
+
+While Features may be installed on top of any base image, the implementation of a Feature might restrict it to a subset of possible base images. For example, some Features may be authored to work with a certain Linux distro (e.g. debian-based images that use the apt package manager).
+
+A Feature is a self contained entity in a folder with at least a [=devcontainer-feature.json=] and `install.sh` entrypoint script. Additional files are permitted and are packaged along side the required files.
+
+
+feature/
+├── devcontainer-feature.json
+├── install.sh
+├── my-file.txt
+└── hello-world.md
+
+
+## devcontainer-feature.json
+
+The `devcontainer-feature.json` file defines metadata about a given Feature. All properties are optional except for `id`, `version`, and `name`.
+
+
+dictionary DevcontainerFeatureJSON {
+ required DOMString id;
+ required DOMString version;
+ required DOMString name;
+ DOMString description;
+ DOMString documentationURL;
+ DOMString licenseURL;
+ sequence keywords;
+ object options;
+ object containerEnv;
+ boolean privileged;
+ boolean init;
+ sequence capAdd;
+ sequence securityOpt;
+ DOMString entrypoint;
+ object customizations;
+ sequence installsAfter;
+ sequence legacyIds;
+ boolean deprecated;
+ object mounts;
+};
+
+
+- {{id}}: Identifier of the Feature. Must be unique in the context of the repository where the Feature exists and must match the name of the directory where the devcontainer-feature.json resides.
+
+- {{version}}: The semantic version of the Feature (e.g., 1.0.0).
+
+- {{name}}: A "human-friendly" display name for the Feature.
+
+- {{description}}: Description of the Feature.
+
+- {{documentationURL}}: URL that points to the documentation of the Feature.
+
+- {{licenseURL}}: URL that points to the license of the Feature.
+
+- {{keywords}}: List of strings relevant to a user that would search for this definition/Feature.
+
+- {{options}}: A map of options that will be passed as environment variables to the execution of the script.
+
+- {{containerEnv}}: A set of name-value pairs that sets or overrides environment variables.
+
+- {{privileged}}: Sets privileged mode for the container (required by things like [docker-in-docker](https://github.com/devcontainers/features/tree/main/src/docker-in-docker)) when the feature is used.
+
+- {{init}}: Adds the tiny init process to the container (`--init`) when the Feature is used.
+
+- {{capAdd}}: Adds container capabilities when the Feature is used.
+
+- {{securityOpt}}: Sets container security options like updating the seccomp profile when the Feature is used.
+
+- {{entrypoint}}: Set if the feature requires an "entrypoint" script that should fire at container startup.
+
+- {{customizations}}: Product-specific properties, each namespace under customizations is treated as a separate set of properties. For each of these sets, the object is parsed, values are replaced while arrays are set as a union.
+
+- {{installsAfter}}: Array of IDs of Features (omitting a version tag) that should execute before this one. Allows control for Feature authors on soft dependencies between different Features.
+
+- {{legacyIds}}: Array of old IDs used to publish this Feature.
+
+ The property is useful for renaming a currently published Feature within a single namespace.
+
+- {{deprecated}}: Indicates that the Feature is deprecated, and will not receive any further updates/support. This property is intended to be used by the supporting tools for highlighting Feature deprecation.
+
+- {{mounts}}: Defaults to unset. Cross-orchestrator way to add additional mounts to a container. Each value is an object that accepts the same values as the Docker CLI `--mount` flag. The Pre-defined devcontainerId variable may be referenced in the value.
+
+
+ {
+ "mounts": [
+ {
+ "source": "dind-var-lib-docker",
+ "target": "/var/lib/docker",
+ "type": "volume"
+ }
+ ]
+ }
+
diff --git a/proposals/declarative-secrets.md b/proposals/declarative-secrets.md
deleted file mode 100644
index aa326450..00000000
--- a/proposals/declarative-secrets.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# Declarative Secrets
-
-## Motiviation
-
-Various projects exist in the wild that require various secrets for them to run properly. Examples include:
-
-- https://github.com/lostintangent/codespaces-langchain
-- https://github.com/openai/openai-quickstart-python
-- https://github.com/openai/openai-quickstart-node
-
-Today these projects have to include specific instructions e.g. in their README telling users where to procure what they need to run and then how to set it up as a secret or add it as an environment variable. This currently acts as an impediment to adoption and promotion of dev containers for these projects.
-
-## Goal
-
-Simplify using dev containers for these kinds of projects by supporting secrets as a first-class part of the dev container creation flow.
-
-## Proposal
-
-Add an optional `secrets` property to the `devContainer.base.schema.json`. This will be used to declare the secrets needed within the dev container.
-
-Property | Type | Description
---- | --- | ---
-`secrets` | `object` | The keys of this object are the names of the secrets that are in use. Keys should be [valid Linux environment variable names](https://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html).
-
-The `secrets` property contains a map of secret names and details about those secrets. These `secrets` are recommended to the user but are not _required_ for creation. All properties are optional.
-
-Property | Type | Description
---- | --- | ---
-`description` | `string` | A brief description of the secret.
-`documentationUrl` | `string` | A URL pointing to where the user can obtain more information about the secret. For example where to find docs on provisioning an API key for a service.
-
-## Example
-
-```json
-{
- "image": "mcr.microsoft.com/devcontainers/base:bullseye",
- "secrets": {
- "CHAT_GPT_API_KEY": {
- "description": "I'm your super cool API key for ChatGPT.",
- "documentationUrl": "https://openai.com/api/"
- },
- "STABLE_DIFFUSION_API_KEY": {}
- }
-}
-```
-
-This example would declare that this dev container wants the user to provide two secrets. The `CHAT_GPT_API_KEY` secret also provides some additional metadata that clients can use in displaying a user experience to provide that secret. The `STABLE_DIFFUSION_API_KEY` skips that metadata.
-
-Implementations _may_ inject these secrets into the container as environment variables.
-
-## Possible Future Extensions
-
-These are **out of scope** for this proposal but the following has been discussed in relation:
-
-1. Inclusion of a `type` field per secret. The default, which we are assuming and leveraging here, would be `"environmentVariable"`. This would include an option to specify `"reference"` and then reference the provided secrets in other parts of the dev container.
-2. Prescriptions of _how_ the secrets are injected into the dev container.
\ No newline at end of file
diff --git a/proposals/devcontainer-id-variable.md b/proposals/devcontainer-id-variable.md
deleted file mode 100644
index 8b2f4c4c..00000000
--- a/proposals/devcontainer-id-variable.md
+++ /dev/null
@@ -1,60 +0,0 @@
-## Goal
-
-Allow features to refer to an identifier that is unique to the dev container they are installed into and that is stable across rebuilds.
-
-E.g., the `docker-in-docker` feature needs a way to mount a volume per dev container.
-
-## Proposal
-
-The identifier will be referred to as `${devcontainerId}` in the devcontainer.json and the feature metadata and that will be replaced with the dev container's id. It should only be used in parts of the configuration and metadata that is not used for building the image because that would otherwise prevent pre-building the image at a time when the dev container's id is not known yet. Excluding boolean, numbers and enum properties the properties supporting `${devcontainerId}` in the devcontainer.json are: `name`, `runArgs`, `initializeCommand`, `onCreateCommand`, `updateContentCommand`, `postCreateCommand`, `postStartCommand`, `postAttachCommand`, `workspaceFolder`, `workspaceMount`, `mounts`, `containerEnv`, `remoteEnv`, `containerUser`, `remoteUser`, `customizations`. Excluding boolean, numbers and enum properties the properties supporting `${devcontainerId}` in the feature metadata are: `entrypoint`, `mounts`, `customizations`.
-
-Implementations can choose how to compute this identifier. They must ensure that it is unique among other dev containers on the same Docker host and that it is stable across rebuilds of dev containers. The identifier must only contain alphanumeric characters. We describe a way to do this below.
-
-### Label-based Implementation
-
-The following assumes that a dev container can be identified among other dev containers on the same Docker host by a set of labels on the container. Implementations may choose to follow this approach.
-
-The identifier is derived from the set of container labels uniquely identifying the dev container. It is up to the implementation to choose these labels. E.g., if the dev container is based on a local folder the label could be named `devcontainer.local_folder` and have the local folder's path as its value.
-
-E.g., the [`ghcr.io/devcontainers/features/docker-in-docker` feature](https://github.com/devcontainers/features/blob/main/src/docker-in-docker/devcontainer-feature.json) could use the dev container id with:
-
-```jsonc
-{
- "id": "docker-in-docker",
- "version": "1.0.4",
- // ...
- "mounts": [
- {
- "source": "dind-var-lib-docker-${devcontainerId}",
- "target": "/var/lib/docker",
- "type": "volume"
- }
- ]
-}
-```
-
-### Label-based Computation
-
-- Input the labels as a JSON object with the object's keys being the label names and the object's values being the labels' values.
- - To ensure implementations get to the same result, the object keys must be sorted and any optional whitespace outside of the keys and values must be removed.
-- Compute a SHA-256 hash from the UTF-8 encoded input string.
-- Use a base-32 encoded representation left-padded with '0' to 52 characters as the result.
-
-JavaScript implementation taking an object with the labels as argument and returning a string as the result:
-```js
-const crypto = require('crypto');
-
-function uniqueIdForLabels(idLabels) {
- const stringInput = JSON.stringify(idLabels, Object.keys(idLabels).sort()); // sort properties
- const bufferInput = Buffer.from(stringInput, 'utf-8');
-
- const hash = crypto.createHash('sha256')
- .update(bufferInput)
- .digest();
-
- const uniqueId = BigInt(`0x${hash.toString('hex')}`)
- .toString(32)
- .padStart(52, '0');
- return uniqueId;
-}
-```
diff --git a/proposals/devcontainer-lockfile.md b/proposals/devcontainer-lockfile.md
deleted file mode 100644
index d35a41b4..00000000
--- a/proposals/devcontainer-lockfile.md
+++ /dev/null
@@ -1,67 +0,0 @@
-## Goal
-
-Introduce a lockfile that records the exact version, download information and checksums for each feature listed in the devcontainer.json.
-
-This will allow for:
-- Improved reproducibility of image builds (installing "latest" of a tool will still have different outcomes as the tool publishes new releases).
-- Improved cachability of image builds (image cache checksums will remain stable when the lockfile pins a feature to a particular version).
-- Improved security by detecting when a feature's release artifact changes after its checksum was first recorded in the lockfile ("trust on first use").
-
-## Proposal
-
-(The following is inspired by NPM's `package-lock.json` and Yarn's `yarn.lock`.)
-
-Each feature is recorded with the identifier and version it is referred to in the devcontainer.json as its key and the following properties as its values:
-- `resolved`:
- - OCI feature: A qualified feature id with the sha256 hash (not the version number).
- - tarball feature: The `https:` URL used to download the feature.
-- `version`: The full version number.
-- `integrity`: `sha256:` followed by the hex encoded SHA-256 checksum of the download artifact.
-- `dependsOn`: An array of feature identifiers equal to the feature's `dependsOn` keys in its `devcontainer-feature.json` including any version or checksum suffix. If the array is empty, this property can be omitted. For every feature listed here, the lockfile will also have a feature record.
-
-The feature identifiers recorded as keys and in the `dependsOn` arrays are converted to lowercase to simplify lookups and comparisons. Note that the `devcontainer.json` and `devcontainer-features.json` may refer to the same features with different casing because these identifiers are not case-senstive.
-
-Local features and the deprecated GitHub releases features are not recorded in the lockfile.
-
-The lockfile is named `devcontainer-lock.json`, is located in the same folder as the `devcontainer.json` and contains a JSON object with a `"features"` property holding the above keys.
-
-Example:
-
-```jsonc
-{
- "features": {
- "ghcr.io/devcontainers/features/node:1": {
- "version": "1.0.4",
- "resolved": "ghcr.io/devcontainers/features/node@sha256:567d704b3f4d3eca3acee51ded7c460a8395436d135d53d1175fb565daff42b8",
- "integrity": "sha256:567d704b3f4d3eca3acee51ded7c460a8395436d135d53d1175fb565daff42b8"
- },
- "https://mycustomdomain.com/devcontainer-feature-myfeature.tgz": {
- "version": "1.2.3",
- "resolved": "https://mycustomdomain.com/devcontainer-feature-myfeature.tgz",
- "integrity": "sha256:567d704b3f4d3eca3acee51ded7c460a8395436d135d53d1175fb565daff42b8"
- }
- }
-}
-```
-
-Example with dependency:
-
-```jsonc
-{
- "features": {
- "ghcr.io/codspace/dependson/a": {
- "version": "1.2.1",
- "resolved": "ghcr.io/codspace/dependson/a@sha256:932027ef71da186210e6ceb3294c3459caaf6b548d2b547d5d26be3fc4b2264a",
- "integrity": "sha256:932027ef71da186210e6ceb3294c3459caaf6b548d2b547d5d26be3fc4b2264a",
- "dependsOn": [
- "ghcr.io/codspace/dependson/e:2"
- ]
- },
- "ghcr.io/codspace/dependson/e:2": {
- "version": "2.3.4",
- "resolved": "ghcr.io/codspace/dependson/e@sha256:9f36f159c70f8bebff57f341904b030733adb17ef12a5d58d4b3d89b2a6c7d5a",
- "integrity": "sha256:9f36f159c70f8bebff57f341904b030733adb17ef12a5d58d4b3d89b2a6c7d5a"
- }
- }
-}
-```
diff --git a/proposals/devcontainer-templates-distribution.md b/proposals/devcontainer-templates-distribution.md
deleted file mode 100644
index efc1659b..00000000
--- a/proposals/devcontainer-templates-distribution.md
+++ /dev/null
@@ -1,129 +0,0 @@
-# Distribution and Discovery of Dev Container Templates
-
-**TL;DR Check out the [quick start repository](https://github.com/devcontainers/template-starter) to get started on distributing your own Dev Container Templates.**
-
-This specification defines a pattern where community members and organizations can author and self-publish [Dev Container Templates](./devcontainer-templates.md).
-
-Goals include:
-
-- For Template authors, create a "self-service" way to publish a Template, either publicly or privately, that is not centrally controlled.
-- Provide the ability to standardize publishing such that supporting tools may implement their own mechanism to aid Template discoverability as they see fit.
-
-## Source code
-
-A Template's source code is stored in a git repository.
-
-For ease of authorship and maintenance, [1..n] Templates can share a single git repository. This set of Templates is referred to as a "collection," and will share the same [`devcontainer-collection.json`](#devcontainer-collection.json) file and "namespace" (eg. `/`).
-
-> **Note:** Templates and [Features](./devcontainer-features.md) should be placed in different git repositories.
-
-Source code for a set of Templates follows the example file structure below:
-
-```
-.
-├── README.md
-├── src
-│ ├── dotnet
-│ │ ├── devcontainer-template.json
-│ │ ├── .devcontainer
-│ │ ├── devcontainer.json
-│ │ └── ...
-│ │ ├── ...
-| ├
-│ ├── docker-from-docker
-│ │ ├── devcontainer-template.json
-│ │ ├── .devcontainer
-│ │ ├── devcontainer.json
-│ │ ├── Dockerfile
-│ │ └── ...
-│ │ ├── ...
-| ├
-│ ├── go-postgres
-│ │ ├── devcontainer-template.json
-│ │ ├── .devcontainer
-│ │ ├── devcontainer.json
-│ │ ├── docker-compose.yml
-│ │ ├── Dockerfile
-│ │ └── ...
-│ │ ├── ...
-```
-
-...where `src` is a directory containing a sub-folder with the name of the Template (e.g. `src/dotnet` or `src/docker-from-docker`) with at least a file named `devcontainer-template.json` that contains the Template metadata, and a `.devcontainer/devcontainer.json` that the supporting tools will drop into an existing project or folder.
-
-Each sub-directory should be named such that it matches the `id` field of the `devcontainer-template.json`. Other files can also be included in the Templates's sub-directory, and will be included during the [packaging step](#packaging) alongside the two required files. Any files that are not part of the Templates's sub-directory (e.g. outside of `src/dotnet`) will not included in the [packaging step](#packaging).
-
-## Versioning
-
-Each Template is individually [versioned according to the semver specification](https://semver.org/). The `version` property in the respective `devcontainer-template.json` file is parsed to determine if the Template should be republished.
-
-Tooling that handles publishing Templates will not republish Templates if that exact version has already been published; however, tooling must republish major and minor versions in accordance with the semver specification.
-
-## Packaging
-
-Templates are distributed as tarballs. The tarball contains the entire contents of the Template sub-directory, including the `devcontainer-template.json`, `.devcontainer/devcontainer.json`, and any other files in the directory.
-
-The tarball is named `devcontainer-template-.tgz`, where `` is the Templates's `id` field.
-
-A reference implementation for packaging and distributing Templates is provided as a GitHub Action (https://github.com/devcontainers/action).
-
-### devcontainer-collection.json
-
-The `devcontainer-collection.json` is an auto-generated metadata file.
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `sourceInformation` | object | Metadata from the implementing packaging tool. |
-| `templates` | array | The list of Templates that are contained in this collection.|
-
-Each Template's `devcontainer-template.json` metadata file is appended into the `templates` top-level array.
-
-## Distribution
-
-There are several supported ways to distribute Templates. Distribution is handled by the implementing packaging tool such as the **[Dev Container CLI](https://github.com/devcontainers/cli)** or **[Dev Container Publish GitHub Action](https://github.com/marketplace/actions/dev-container-publish)**.
-
-A user can add a Template in to their projects as defined by the [supporting Tools](../docs/specs/supporting-tools.md#supporting-tools-and-services).
-
-### OCI Registry
-
-An OCI registry that implements the [OCI Artifact Distribution Specification](https://github.com/opencontainers/distribution-spec) serves as the primary distribution mechanism for Templates.
-
-Each packaged Template is pushed to the registry following the naming convention `//[:version]`, where version is the major, minor, and patch version of the Template, according to the semver specification.
-
-> **Note:** The `namespace` is a unique identifier for the collection of Templates and must be different than the collection of [Features](./devcontainer-features.md). There are no strict rules for the `namespace`; however, one pattern is to set `namespace` equal to source repository's `/`.
-
-A custom media type `application/vnd.devcontainers` and `application/vnd.devcontainers.layer.v1+tar` are used as demonstrated below.
-
-For example, the `go` Template in the `devcontainers/templates` namespace at version `1.2.3` would be pushed to the ghcr.io OCI registry.
-
-> **Note:** The example below uses [`oras`](https://oras.land/) for demonstration purposes. A supporting tool should directly implement the required functionality from the aforementioned OCI artifact distribution specification.
-
-```bash
-# ghcr.io/devcontainers/templates/go:1
-REGISTRY=ghcr.io
-NAMESPACE=devcontainers/templates
-TEMPLATE=go
-
-ARTIFACT_PATH=devcontainer-template-go.tgz
-
-for VERSION in 1 1.2 1.2.3 latest
-do
- oras push ${REGISTRY}/${NAMESPACE}/${TEMPLATE}:${VERSION} \
- --manifest-config /dev/null:application/vnd.devcontainers \
- ./${ARTIFACT_PATH}:application/vnd.devcontainers.layer.v1+tar
-done
-
-```
-
-The "namespace" is the globally identifiable name for the collection of Templates. (eg: `owner/repo` for the source code's git repository).
-
-The auto-generated `devcontainer-collection.json` is pushed to the registry with the same `namespace` as above and no accompanying `template` name. The collection file is always tagged as `latest`.
-
-```bash
-# ghcr.io/devcontainers/templates
-REGISTRY=ghcr.io
-NAMESPACE=devcontainers/templates
-
-oras push ${REGISTRY}/${NAMESPACE}:latest \
- --manifest-config /dev/null:application/vnd.devcontainers \
- ./devcontainer-collection.json:application/vnd.devcontainers.collection.layer.v1+json
-```
diff --git a/proposals/devcontainer-templates.md b/proposals/devcontainer-templates.md
deleted file mode 100644
index 6758f623..00000000
--- a/proposals/devcontainer-templates.md
+++ /dev/null
@@ -1,186 +0,0 @@
-# Dev Container Templates reference
-
-Development container "Templates" are source files packaged together that encode configuration for a complete development environment. A Template can be used in a new or existing project, and a [supporting tool](https://containers.dev/supporting) will use the configuration from the Template to build a development container.
-
-The configuration is placed in a [`.devcontainer/devcontainer.json`](/docs/specs/devcontainer-reference.md#devcontainerjson) which can also reference other files within the Template. A Template can also provide additional source files (eg: boilerplate code or a [lifecycle script](https://containers.dev/implementors/json_reference/#lifecycle-scripts).
-
-Template metadata is captured by a `devcontainer-template.json` file in the root folder of the Template.
-
-## Folder structure
-
-A single Template is a folder with at least a `devcontainer-template.json` and [`.devcontainer/devcontainer.json`](/docs/specs/devcontainer-reference.md#devcontainerjson). Additional files are permitted and are packaged along side the required files.
-
-```
-+-- template
-| +-- devcontainer-template.json
-| +-- .devcontainer
-| +-- devcontainer.json
-| +-- (other files)
-| +-- (other files)
-```
-
-## devcontainer-template.json properties
-
-The `devcontainer-template.json` file defines information about the Template to be used by any [supporting tools](../docs/specs/supporting-tools.md#supporting-tools-and-services).
-
-The properties of the file are as follows:
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `id` | string | ID of the Template. The `id` should be unique in the context of the repository/published package where the Template exists and must match the name of the directory where the `devcontainer-template.json` resides. |
-| `version` | string | The semantic version of the Template. |
-| `name` | string | Name of the Template. |
-| `description` | string | Description of the Template. |
-| `documentationURL` | string | Url that points to the documentation of the Template. |
-| `licenseURL` | string | Url that points to the license of the Template. |
-| `options` | object | A map of options that the supporting tools should use to populate different configuration options for the Template. |
-| `platforms` | array | Languages and platforms supported by the Template. |
-| `publisher` | string | Name of the publisher/maintainer of the Template. |
-| `keywords` | array | List of strings relevant to a user that would search for this Template. |
-
-### The `options` property
-
-The `options` property contains a map of option IDs and their related configuration settings. These `options` are used by the supporting tools to prompt the user to choose from different Template configuration options. The tools would replace the option ID with the selected value in all the files (within the sub-directory of the Template). This replacement would happen before dropping the `.devcontainer/devcontainer.json` and other files (within the sub-directory of the Template) required to containerize your project. See [option resolution](#option-resolution) for more details. For example:
-
-```json
-{
- "options": {
- "optionId": {
- "type": "string",
- "description": "Description of the option",
- "proposals": ["value1", "value2"],
- "default": "value1"
- }
- }
-}
-```
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `optionId` | string | ID of the option used by the supporting tools to replace the selected value in the files within the sub-directory of the Template. |
-| `optionId.type` | string | Type of the option. Valid types are currently: `boolean`, `string` |
-| `optionId.description` | string | Description for the option. |
-| `optionId.proposals` | array | A list of suggested string values. Free-form values **are** allowed. Omit when using `optionId.enum`. |
-| `optionId.enum` | array | A strict list of allowed string values. Free-form values are **not** allowed. Omit when using `optionId.proposals`. |
-| `optionId.default` | string | Default value for the option. |
-
-> `Note`: The `options` must be unique for every `devcontainer-template.json`
-
-### Referencing a Template
-
-The `id` format (`//[:]`) dictates how a [supporting tool](https://containers.dev/supporting) will locate and download a given Template from an OCI registry. For example:
-
-- `ghcr.io/user/repo/go`
-- `ghcr.io/user/repo/go:1`
-- `ghcr.io/user/repo/go:latest`
-
-The registry must implement the [OCI Artifact Distribution Specification](https://github.com/opencontainers/distribution-spec). Some implementors can be [found here](https://oras.land/implementors/).
-
-## Versioning
-
-Each Template is individually [versioned according to the semver specification](https://semver.org/). The `version` property in the respective `devcontainer-template.json` file is updated to increment the Template's version.
-
-Tooling that handles releasing Templates will not republish Templates if that exact version has already been published; however, tooling must republish major and minor versions in accordance with the semver specification.
-
-## Release
-
-_For information on distributing Templates, see [devcontainer-templates-distribution.md](./devcontainer-templates-distribution.md)._
-
-### Option Resolution
-
-A Template's `options` property is used by a supporting tool to prompt for different configuration options. A supporting tool will parse the `options` object provided by the user. If a value is selected for a Template, it will be replaced in the files (within the sub-directory of the Template).
-
-### Option resolution example
-
-Consider a `java` Template with the following folder structure:
-
-```
-+-- java
-| +-- devcontainer-template.json
-| +-- .devcontainer
-| +-- devcontainer.json
-```
-
-Suppose the `java` Template has the following `options` parameters declared in the `devcontainer-template.json` file:
-
-```json
-// ...
-"options": {
- "imageVariant": {
- "type": "string",
- "description": "Specify version of java.",
- "proposals": [
- "17-bullseye",
- "17-buster",
- "11-bullseye",
- "11-buster",
- "17",
- "11"
- ],
- "default": "17-bullseye"
- },
- "nodeVersion": {
- "type": "string",
- "proposals": [
- "latest",
- "16",
- "14",
- "10",
- "none"
- ],
- "default": "latest",
- "description": "Specify version of node, or 'none' to skip node installation."
- },
- "installMaven": {
- "type": "boolean",
- "description": "Install Maven, a management tool for Java.",
- "default": "false"
- },
-}
-```
-
-and it has the following `.devcontainer/devcontainer.json` file:
-
-```json
-{
- "name": "Java",
- "image": "mcr.microsoft.com/devcontainers/java:0-${templateOption:imageVariant}",
- "features": {
- "ghcr.io/devcontainers/features/node:1": {
- "version": "${templateOption:nodeVersion}",
- "installMaven": "${templateOption:installMaven}"
- }
- },
-// ...
-}
-```
-
-A user tries to add the `java` Template to their project using the [supporting tools](../docs/specs/supporting-tools.md#supporting-tools-and-services) and selects `17-bullseye` when prompted for `"Specify version of Go"` and the `default` values when prompted for `"Specify version of node, or 'none' to skip node installation"` and `"Install Maven, a management tool for Java"`.
-
-The supporting tool could then use a string replacer for all the files within the sub-directory of the Template. In this example, `.devcontainer/devcontainer.json` needs to be modified and hence, the inputs can provided to it as follows:
-
-```
-{
- imageVariant:"17-bullseye",
- nodeVersion: "latest",
- installMaven: "false"
-}
-```
-
-The modified `.devcontainer/devcontainer.json` will be as follows:
-
-```json
-{
- "name": "Go",
- "image": "mcr.microsoft.com/devcontainers/go:0-17-bullseye",
- "features": {
- "ghcr.io/devcontainers/features/node:1": {
- "version": "latest",
- "installMaven": "false"
- }
- },
- ...
-}
-```
-
-The modified `.devcontainer/devcontainer.json` would be dropped into any existing folder as a starting point for containerizing your project.
diff --git a/proposals/feature-dependencies.md b/proposals/feature-dependencies.md
deleted file mode 100644
index b8885702..00000000
--- a/proposals/feature-dependencies.md
+++ /dev/null
@@ -1,238 +0,0 @@
-# Feature Dependencies
-
-Reference: https://github.com/devcontainers/spec/issues/109
-
-**NOTE**: A reference implementation was introduced in https://github.com/devcontainers/cli/commit/236b85162a945a1af9e72fcbe02eb5c7c864b31d
-
-## Motivation
-
-We've seen significant interest in the ability to "reuse" or "extend" a given Feature with one or more additional Features. Often in software a given tool depends on another (or several) tool(s)/framework(s). As the dev container Feature ecosystem has grown, there has been a growing need to reduce redundant code in Features by first installing a set of dependent Features.
-
-## Goal
-
-The solution shall provide a way to publish a Feature that "depends" on >= 1 other published Features. Dependent Features will be installed by the orchestrating tool following this specification.
-
-The solution outlined shall not only execute the installation scripts, but also merge the additional development container config, as outlined in the documented [merging logic](https://containers.dev/implementors/spec/#merge-logic).
-
-The solution should provide guidelines for Feature authorship, and prefer solutions that enable simple authoring of Features, as well as easy consumption by end-users.
-
-A non-goal is to require the use or implementation of a full-blown dependency management system (such as `npm` or `apt`). The solution should allow Features to operate as "self-contained, shareable units of installation code and development container configuration"[(1)](https://containers.dev/implementors/features/).
-
-## Definitions
-
-- **User-defined Feature**. Features defined explicitly by the user in the `features` object of `devcontainer.json`.
-- **Published Feature**. Features published to an OCI registry or a direct HTTPS link to a Feature tgz.
-
-## Existing Solutions
-
-See https://github.com/devcontainers/spec/pull/208/files#diff-a29ffaac693437b6fbf001066b97896f7aef4d6d37dc65b8b98b22a5e19f6c7aR26 for existing solutions and alternative approaches.
-
-## Proposed Specification
-
-### (A) Add `dependsOn` property
-
-A new property `dependsOn` can be optionally added to the `devcontainer-feature.json`. This property mirrors the `features` object in `devcontainer.json`. Adding Feature(s) to this property tells the orchestrating tool to install the Feature(s) (with the associated options, if provided) before installing the Feature that declares the dependency.
-
-> This property is similar to the existing `installsAfter` property, with the key distinctions that `installsAfter` (1) is **not** recursive, (2) indicates a soft dependency to influence installation order **if and only if a given Feature is already set to be installed via a user-defined Feature or transitively through a user-defined Feature**, and (3) Features indicated by `installsAfter` can not provide options, nor are they able to be pinned to a specific version tag or digest.
-
-The installation order is subject to the algorithm set forth in this document. Where there is ambiguity, it is up to the orchestrating tool to decide the order of installation. Implementing tools should provide a consistent installation order in instances of ambiguity (i.e sort alphanumerically by identifier).
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `dependsOn` | `object` | The ID and options of the Feature dependency. Pinning to version tags or digests are honored. When published, the ID must refer to either a Feature (1) published to an OCI registry, (2) a Feature Tgz URI, or (3) a Feature in the local file tree (**). Otherwise, IDs follow the same semantics of the `features` object in `devcontainer.json`. (a.k.a "Hard Dependency") |
-
-
-(**) Deprecated Feature identifiers (i.e GitHub Release) are not supported and the presence of this property may be considered a fatal error or ignored. For [local Features (ie: during development)](https://containers.dev/implementors/features-distribution/#addendum-locally-referenced), you may also depend on other local Features by providing a relative path to the Feature, relative to folder containing the active `devcontainer.json`. This behavior of Features within this property again mirror the `features` object in `devcontainer.json`.
-
-An example `devcontainer-feature.json` file with a dependency on four other published Features:
-
-```json
-{
- "name": "My Feature",
- "id": "myFeature",
- "version": "1.0.0",
- "dependsOn": {
- "ghcr.io/second:1": {
- "flag": true
- },
- "features.azurecr.io/third:1": {},
- "features.azurecr.io/fourth:1.2.3": {},
- "features.azurecr.io/fifth@sha256:a4cdc44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" {},
- }
-}
-```
-
-`myfeature` will be installed after `second`, `third`, `fourth`, and `fifth`.
-
-The following three sections will illustrate how an orchestrating tool shouuld identify dependencies between Features, depending on [how the Feature is referenced](https://containers.dev/implementors/features/#referencing-a-feature).
-
-#### Identifying Dependencies - OCI Registry
-
-To speed up dependency resolution, all Features [published to an OCI registry](https://containers.dev/implementors/features-distribution/#oci-registry) will have their entire `devcontainer-feature.json` serialized and added as an [annotation](https://github.com/opencontainers/image-spec/blob/main/annotations.md).
-
-The orchestrating tool can use this annotation to resolve the Feature's dependencies without having to download and extract the Feature's tarball.
-
-More specifically, an [annotation](https://github.com/opencontainers/image-spec/blob/main/annotations.md) named `dev.containers.metadata` will be populated on the manifest when published by an implementing tool. This annotation is the escaped JSON object of the entire `devcontainer-feature.json` as it appears during the [packaging stage](https://containers.dev/implementors/features-distribution/#packaging).
-
-An example manifest with the `dev.containers.metadata` annotation:
-
-```json
-{
- "schemaVersion": 2,
- "mediaType": "application/vnd.oci.image.manifest.v1+json",
- "config": {
- "mediaType": "application/vnd.devcontainers",
- "digest": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
- "size": 0
- },
- "layers": [
- {
- "mediaType": "application/vnd.devcontainers.layer.v1+tar",
- "digest": "sha256:738af5504b253dc6de51d2cb1556cdb7ce70ab18b2f32b0c2f12650ed6d2e4bc",
- "size": 3584,
- "annotations": {
- "org.opencontainers.image.title": "devcontainer-feature-myFeature.tgz"
- }
- }
- ],
- "annotations": {
- "dev.containers.metadata": "{\"name\": \"My Feature\",\"id\": \"myFeature\",\"version\": \"1.0.0\",\"dependsOn\": {\"ghcr.io/myotherFeature:1\": {\"flag\": true},\"features.azurecr.io/aThirdFeature:1\": {},\"features.azurecr.io/aFourthFeature:1.2.3\": {}}}"
- }
-}
-```
-
-> If no annotation is present on a Feature's manifest, the orchestrating tool MUST fallback to downloading and extracting the Feature's contents to read the metadata properties. Failure to do so may result in a Feature being installed without its dependencies (eg: `installsAfter`).
-
-In summary, supporting tools may choose to identify the dependencies of the declared user-defined Features by fetching the manifest of the Features and reading the `dependsOn` and `installsAfter` properties from the `dev.containers.metadata` annotation. This will allow the orchestrating tool to recursively resolve all dependencies without having to download and extract each Feature's tarball.
-
-#### Identifying Dependencies - HTTPS Direct Tarball
-
-Published Features referenced directly by [HTTPS URI pointing to the packaged tarball archive](https://containers.dev/implementors/features-distribution/#directly-reference-tarball) will need to be fully downloaded an extracted to read the `dependsOn` property.
-
-#### Identifying Dependencies - Local Features
-
-[Local Features](https://containers.dev/implementors/features-distribution/#addendum-locally-referenced) dependencies are identified by directly reading the `dependsOn` property in the associated `devcontainer-feature.json` metadata file.
-
-### (B) `dependsOn` install order algorithm
-
-The orchestrating tool is responsible for calculating a Feature installation order (or error, if no valid installation order can be resolved). The set of Features to be installed is the union of user-defined Features and their dependencies. The orchestrating tool will perform the following steps:
-
-#### **(B1) Building dependency graph**
-
-From the user-defined Features, the orchestrating tool will build a dependency graph. The graph will be built by traversing the `dependsOn` and `installsAfter` properties of each Feature. The metadata for each dependency is then fetched and the node added as an edge to to the dependent Feature. For `dependsOn` dependencies, the dependency will be fed back into the worklist to be recursively resolved.
-
-An accumulator is maintained with all uniquely discovered and user-provided Features, each with a reference to its dependencies. If the exact Feature (see **Feature Equality**) has already been added to the accumulator, it will not be added again. The accumulator will be fed into (B3) after the Feature tree has been resolved.
-
-The graph may be stored as an adjacency list with two kinds of edges (1) `dependsOn` edges or "hard dependencies" and (2) `installsAfter` edges or "soft dependencies".
-
-#### **(B2) Assigning `roundPriority`**
-
-Each node in the graph has an implicit, default `roundPriority` of 0.
-
-To influence installation order globally while still honoring the dependency graph of built in **(B1)**, `roundPriority` values may be tweaks for each Feature. When each round is calculated in **(B3)**, only the Features equal to the max `roundPriority` of that set will be committed (the remaining will be uncommitted and reevaulated in subsequent rounds).
-
-The `roundPriority` is set to a non-zero value in the following instances:
-
-- If the [`devcontainer.json` contains an `overrideFeatureInstallOrder`](#overridefeatureinstallorder).
-
-#### **(B3) Round-based sorting**
-
-Perform a sort on the result of **(B1)** in rounds. This sort will rearrange Features, producing a sorted list of Features to install. The sort will be performed as follows:
-
-Start with all the elements from **(B2)** in a `worklist` and an empty list `installationOrder`. While the `worklist` is not empty, iterate through each element in the `worklist` and check if all its dependencies (if any) are already members of `installationOrder`. If the check is true, add it to an intermediate list `round` If not, skip it. Equality is determined in **Feature Equality**.
-
-Then for each intermediate `round` list, commit to `installationOrder` only those nodes who share the maximum `roundPriority`. Return all nodes in `round` with a strictly lower `roundPriority` to the `worklist` to be reprocessed in subsequent iterations. If there are multiple nodes with the same `roundPriority`, commit them to `installationOrder` with a final sort according to **Round Stable Sort**.
-
-Repeat for as many rounds as necessary until `worklist` is empty. If there is ever a round where no elements are added to `installationOrder`, the algorithm should terminate and return an error. This indicates a circular dependency or other fatal error in the dependency graph. Implementations should attempt to provide the user with information about the error and possible mitigation strategies.
-
-
-#### Definition: Feature Equality
-
-This specification defines two Features as equal if both Features point to the same exact contents and are executed with the same options.
-
-**For Features published to an OCI registry**, two Feature are identical if their manifest digests are equal, and the options executed against the Feature are equal (compared value by value). Identical manifest digests implies that the tgz contents of the Feature and its entire `devcontainer-feature.json` are identical. If any of these conditions are not met, the Features are considered not equal.
-
-**For Features fetched by HTTPS URI**, two Features are identical if the contents of the tgz are identical (hash to the same value), and the options executed against the Feature are equal (compared value by value). If any of these conditions are not met, the Features are considered not equal.
-
-**For local Features**, each Feature is considered unique and not equal to any other local Feature.
-
-#### Definition: Round Stable Sort
-
-To prevent non-deterministic behavior, the algorithm will sort each **round** according to the following rules:
-
-- Compare and sort each Feature lexiographically by their fully qualified resource name (For OCI-published Features, that means the ID without version or digest.). If the comparison is equal:
-- Compare and sort each Feature from oldest to newest tag (`latest` being the "most new"). If the comparision is equal:
-- Compare and sort each Feature by their options by:
- - Greatest number of user-defined options (note omitting an option will default that value to the Feature's default value and is not considered a user-defined option). If the comparison is equal:
- - Sort the provided option keys lexicographically. If the comparison is equal:
- - Sort the provided option values lexicographically. If the comparision is equal:
-- Sort Features by their canonical name (For OCI-published Features, the Feature ID resolved to the digest hash).
-
-If there is no difference based on these comparator rules, the Features are considered equal.
-
-## Note: Existing methods of altering Feature installation order
-
-Two existing properties (1) `installsAfter` on the Feature metadata, and (2) `overrideFeatureInstallationOrder` in the `devcontainer.json` both exist to alter the installation order of user-defined Features. The behavior of these properties are carried forward in this proposal.
-
-### installsAfter
-
-The `installsAfter` property is a "soft dependency" that influences the installation order of Features that are queued to be installed. The effective behavior of this property is the same as `dependsOn`, with the following differences:
-
-- `installsAfter` is not recursive.
-- `installsAfter` only influences the installation order of Features that are already set to be installed after resolving the dependency tree.
-- The Feature indicated by `installsAfter` can not provide options, nor are they able to be pinned to a specific version tag or digest. This is unchanged from the current specification.
-
-From an implementation point of view, `installsAfter` nodes may be added as a seperate set of directed edges, just as `dependsOn` nodes are added as directed edges (see **(B1)**). Before round-based installation and sorting **(B3)**, an orchestrating tool should remove all `installsAfter` directed edges that do not correspond with a Feature in the `worklist` that is set to be installed. In each round, a Feature can then be installed if all its requirements (both `dependsOn` and `installsAfter` dependencies) have been fulfilled in previous rounds.
-
-An implemention should fail the dependency resolution step if the evaluation of the `installsAfter` property results in an inconsistent state (eg: a circular dependency).
-
-### overrideFeatureInstallOrder
-
-The `overrideFeatureInstallOrder` property of `devcontainer.json` is an array of Feature IDs that are to be installed in descending priority order as soon as its dependencies outlined above are installed.
-
-This evaluation is performed by assigning a [`roundPriority`](#b2-assigning-roundpriority) to all nodes that match match the Feature identifier present in the property.
-
-For example, given `n` Features in the `overrideFeatureInstallOrder` array, the orchestrating tool should assign a `roundPriority` of `n - idx` to each Feature, where `idx` is the zero-based index of the Feature in the array.
-
-For example:
-
-```json
-overrideFeatureInstallOrder = [
- "foo",
- "bar",
- "baz"
-]
-```
-
-would result in the following `roundPriority` assignments:
-
-```json
-const roundPriority = {
- "foo": 3,
- "bar": 2,
- "baz": 1
-}
-```
-
-This property must not influence the dependency relationship as defined by the dependency graph (see **(B1)**) and shall only be evaulated at the round-based sorting step (see **(B3)**). Put another way, this property cannot "pull forward" a Feature until all of its dependencies (both soft and hard) have been installed. After a Feature's dependencies have been installed in other rounds, this property should "pull forward" each Feature as early as possible (given the order of identifiers in the array).
-
-Similar to `installsAfter`, this property's members may not provide options, nor are they able to be pinned to a specific version tag or digest. This is unchanged from the current specification.
-
-If a Feature is indicated in `overrideFeatureInstallOrder` but not a member of the dependency graph (it is not queued to be installed), the orchestrating tool may fail the dependency resolution step.
-
-## Additional Remarks
-
-### Feature authorship
-
-Features should be authored with the following considerations:
-
-- Features should be authored with the assumption that they will be installed in any order, so long as the dependencies are met at some point beforehand.
-- Since two Features with different options are considered different, a single Feature may be installed more than once. Features should be idempotent.
-- Features that require updating shared state in the container (eg: updating the `$PATH`), should be aware that the same Feature may be run multiple times. Consider a method for previous runs of the Feature to communicate with future runs, updating the shared state in the intended way.
-
-
-### Image Metadata
-
-Dependency resolution is only performed on initial container creation by reading the `features` object of `devcontainer.json` and resolving the Features in that point in time. For subsequent creations from an image (or resumes of a dev container), the dependency tree is **not** re-calculated. To re-calculate the dependency tree, the user must delete the image (or dev container) and recreate it from a `devcontainer.json`.
-
-Once Feature dependencies are resolved, they are treated the same as if members of the user-defined Features. That means both user-defined Features and their dependencies are stored in the image's metadata.
\ No newline at end of file
diff --git a/proposals/features-contribute-lifecycle-scripts.md b/proposals/features-contribute-lifecycle-scripts.md
deleted file mode 100644
index bed49c30..00000000
--- a/proposals/features-contribute-lifecycle-scripts.md
+++ /dev/null
@@ -1,122 +0,0 @@
-# [Proposal] Allow Dev Container Features to contribute lifecycle scripts
-
-Related to: https://github.com/devcontainers/spec/issues/60, https://github.com/devcontainers/spec/issues/181
-
-## Goal
-
-Allow Feature authors to provide lifecycle hooks for their Features during a dev container build.
-
-## Proposal
-
-Introduce the following properties to [devcontainer-feature.json](https://containers.dev/implementors/features/#devcontainer-feature-json-properties), mirroring the behavior and syntax of the `devcontainer.json` lifecycle hooks.
-
-- "onCreateCommand"
-- "updateContentCommand"
-- "postCreateCommand"
-- "postStartCommand"
-- "postAttachCommand"
-
-Note that `initializeCommand` is omitted, pending further discussions around a secure design.
-
-As with all lifecycle hooks, commands are executed from the context (cwd) of the [project workspace folder](https://containers.dev/implementors/spec/#project-workspace-folder).
-
-> NOTE: To use any assets (a script, etc...) embedded within a Feature in a lifecycle hook property, it is the Feature author's reponsibility to copy that assert to somewhere on the container where it will persist (outside of `/tmp`.) Implementations are not required to persist Feature install scripts beyond the initial build.
-
-All other semantics match the existing [Lifecycle Scripts](https://containers.dev/implementors/json_reference/#lifecycle-scripts) and [lifecycle script parallel execution](https://containers.dev/implementors/spec/#parallel-exec) behavior exactly.
-
-### Execution
-
-When a dev container is brought up, for each lifecycle hook, each Feature that contributes a command to a lifecycle hook shall have the command executed in sequence, following the same execution order as outlined in [Feature installation order](https://containers.dev/implementors/features/#installation-order), and always before any user-provided lifecycle commands.
-
-## Examples
-
-
-### Executing a script in the workspace folder
-
-The follow example illustrates contributing an `onCreateCommand` and `postCreateCommand` script to `featureA`. At each lifecycle hook during the build, the provided script will be executed in the [project workspace folder](https://containers.dev/implementors/spec/#project-workspace-folder), following the same semantics as [user-defined lifecycle hooks](https://containers.dev/implementors/json_reference/#lifecycle-scripts).
-
-```jsonc
-{
- "id": "featureA",
- "version": "1.0.0",
- "onCreateCommand": "myOnCreate.sh && myOnCreate2.sh",
- "postCreateCommand": "myPostCreate.sh",
- "postAttachCommand": {
- "command01": "myPostAttach.sh arg01",
- "command02": "myPostAttach.sh arg02",
- },
-}
-
-```
-
-### Executing a script bundled with the Feature
-
-The following example illustrates executing a `postCreateCommand` script bundled with the Feature.
-
-```jsonc
-{
- "id": "featureB",
- "version": "1.0.0",
- "postCreateCommand": "/usr/myDir/bundledScript.sh",
- "installsAfter": [
- "featureA"
- ]
-}
-```
-
-The `install.sh` will need to move this script to `/usr/myDir`.
-
-```
-#!/bin/sh
-
-cp ./bundleScript /usr/myDir
-...
-...
-```
-
-Given this example, `featureB`'s file structure would look something like:
-
-```
-.
-├── src
-│ ├── featureB
-│ │ ├── bundledScript.sh
-│ │ ├── devcontainer-feature.json
-│ │ └── install.sh
-```
-
-### Installation
-
-Given the following `devcontainer.json` and the two example Features above.
-
-```jsonc
-{
- "image": "ubuntu",
- "features": {
- "featureA": {},
- "featureB": {},
- },
- "postCreateCommand": "userPostCreate.sh",
- "postAttachCommand": {
- "server": "npm start",
- "db": ["mysql", "-u", "root", "-p", "my database"]
- },
-}
-```
-
-The following timeline of events would occur.
-
-> Note that:
->
->1. Each bullet point below is _blocking_. No subsequent lifecycle commands shall proceed until the current command completes.
-> 2. If one of the lifecycle scripts fails, any subsequent scripts will not be executed. For instance, if a given `postCreate` command fails, the `postStart` hook and any following hooks will be skipped.
->
-
-- `featureA`'s onCreateCommand
-- `featureA`'s postCreateCommand
-- `featureB`'s postCreateCommand
-- The user's postCreateCommand
-- `featureA`'s postAttachCommand **(parallel syntax, each command running in parallel)**
-- The user's postAttachCommand **(parallel syntax, each command running in parallel)**
-
-Suppose `featureB`'s postCreateCommand exited were to exit unsuccessfully (non-zero exit code). In this case, the `postAttachCommand` will never fire.
diff --git a/proposals/features-legacyIds-deprecated-properties.md b/proposals/features-legacyIds-deprecated-properties.md
deleted file mode 100644
index 249f7ebf..00000000
--- a/proposals/features-legacyIds-deprecated-properties.md
+++ /dev/null
@@ -1,80 +0,0 @@
-Goal: Adds support for renaming and deprecating a Feature.
-
-Adding two new properties to the [devcontainer-feature.json](../docs/specs/devcontainer-features.md#devcontainer-featurejson-properties) 👇
-
-# 1. legacyIds
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `legacyIds` | array | Defaults to `[]`. Array of old IDs used to publish this Feature. The property is useful for renaming a currently published Feature within a single namespace. |
-
-## Steps to rename a Feature
-
-1. Update the Feature [source code](../docs/specs/features-distribution/#source-code) folder and the `id` property in the [devcontainer-feature.json properties](../docs/specs/devcontainer-features.md#devcontainer-featurejson-properties) to reflect the new `id`. Other properties (`name`, `documentationUrl`, etc.) can optionally be updated during this step.
-2. Add or update the `legacyIds` property to the Feature, including the previously used `id`.
-3. Bump the semantic version of the Feature.
-4. Rerun the `devcontainer features publish` command, or equivalent tool that implements the [Features distribution specification](../docs/specs/features-distribution/#distribution).
-
-### Example: Renaming a Feature
-
-Let's say we currently have a `docker-from-docker` Feature 👇
-
-Current `devcontainer-feature.json` :
-
-```jsonc
-{
- "id": "docker-from-docker",
- "version": "2.0.1",
- "name": "Docker (Docker-from-Docker)",
- "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-from-docker",
- ....
-}
-```
-
-We'd want to rename this Feature to `docker-outside-of-docker`. The source code folder of the Feature will be updated to `docker-outside-of-docker` and the updated `devcontainer-feature.json` will look like 👇
-
-```jsonc
-{
- "id": "docker-outside-of-docker",
- "version": "2.0.2",
- "name": "Docker (Docker-outside-of-Docker)",
- "documentationURL": "https://github.com/devcontainers/features/tree/main/src/docker-outside-of-docker",
- "legacyIds": [
- "docker-from-docker"
- ]
- ....
-}
-```
-
-**Note** - The semantic version of the Feature defined by the `version` property should be **continued** and should not be restarted at `1.0.0`.
-
-### Changes to the Features distribution specification
-
-- [Tools implementing the Dev Container Features Distribution Specification](../docs/specs/features-distribution/#distribution) (eg: [Dev Container CLI](https://github.com/devcontainers/cli) and [Dev Container Publish GitHub Action](https://github.com/marketplace/actions/dev-container-publish)) will dual publish the old `id`s (defined by the `legacyIds` property), and the new `id`.
- - The [putManifestWithTags](https://github.com/devcontainers/cli/blob/main/src/spec-configuration/containerCollectionsOCIPush.ts#L172) will be modified. The same `tgz` file for the `id` will be pushed to the `id`s mentioned by the `legacyIds` property for all the [tags](https://github.com/devcontainers/cli/blob/main/src/spec-configuration/containerCollectionsOCIPush.ts#L175).
-
-### Supporting backwards compatibility for [`installsAfter`](../docs/specs/devcontainer-features.md#2-the-installsafter-feature-property) property
-
-- Currently the `installsAfter` property is defined as an array consisting of the Feature `id` that should be installed before the given Feature.
-- The Feature to be renamed could be already defined by other Feature authors in their `installsAfter` property. Renaming the `id` could change the installation order for them if the `installsAfter` property is not updated with the new `id`. In order to avoid this unexpected behavior and to support back compat, the CLI tooling will be updated to also look at the `legacyIds` property along with the `id` for determining the installation order.
-
- ### Supporting tools
-
-This property can be used by the supporting tools to indicate Feature rename in few ways
- - [Dev Container Publish GitHub Action](https://github.com/devcontainers/action) which auto-generates the README files can add a note with a list of old `id`s which were used to publish this Feature.
- - In the scenarios where Dev Configs are referencing the old `id`s, the VS Code extension hints could be enhanced to deliver this warning that the `id` was renamed to a new one.
-- The [containers.dev/features](https://containers.dev/features) website, and [supporting tools](https://containers.dev/supporting) like [VS Code Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) and [GitHub Codespaces](https://github.com/features/codespaces) wouldn't list the old `id`, instead list the new `id` of Features.
-
-# 2. deprecated
-
-| Property | Type | Description |
-| :--- | :--- | :--- |
-| `deprecated` | boolean | Defaults to `false`. Indicates that the Feature is deprecated, and will not receive any further updates/support. This property is intended to be used by the supporting tools to highlight Feature deprecation. |
-
-- If this property is set to `true`, then it indicates that the Feature is deprecated and won't be receiving any further updates/support. The OCI artifacts would exist, hence, the current dev configs will continue to work.
-- In case of security or other ciritical updates, the Feature author could still publish a new version of the deprecated Feature by bumping the semantic version of the Feature.
-- This property could be used by the supporting tools to indicate Feature deprecation in few ways -
- - [Dev Container Publish GitHub Action](https://github.com/devcontainers/action) which auto-generates the README files can be updated to add a top-level header mentioning it's deprecation.
- - The [containers.dev/features](https://containers.dev/features) website, and [supporting tools](https://containers.dev/supporting) like [VS Code Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) and [GitHub Codespaces](https://github.com/features/codespaces) wouldn't list the deprecated Features.
- - VS Code extension hints could be enhanced to deliver this information about it's deprecation.
-
\ No newline at end of file
diff --git a/proposals/features-library.md b/proposals/features-library.md
deleted file mode 100644
index 47415b7d..00000000
--- a/proposals/features-library.md
+++ /dev/null
@@ -1,150 +0,0 @@
-# Sharing code between Dev Container Features
-
-ref: https://github.com/devcontainers/spec/issues/129
-
-# Motivation
-
-The current model for authoring Features encourages significant copy and paste between individual Features. Most of the Features published under the `devcontainers/features` namespace contain approximately 100 lines of [identical helper functions](https://github.com/devcontainers/features/blob/main/src/azure-cli/install.sh#L29-L164) before the first line of the script is executed. The process of maintaining these helper functions is tedious, error-prone, and leads to less readable Features.
-
-Additionally, [members of the Feature authoring community have expressed interest in sharing code between Features](https://github.com/orgs/devcontainers/discussions/10). Exploring the source code of self-published Features, it is evident that many authors have copy/pasted code from other Features. This is a sign that there is a need for a more efficient way to share code between Features.
-
-# Goal
-
-Provide a generic and simple way to share code between Features.
-
-# Proposals
-
-## [Proposal A] Add: `include` property to `devcontainer-feature.json`
-
-Add an `include` property to the `devcontainer-feature.json`. This will be honored during the Feature [packaging stage](https://containers.dev/implementors/features-distribution/#packaging).
-
-The contents of the provided relative path is copied into the packaged Feature archive. Files or directories are recursively copied into the archive following the same directory structure as in the source code.
-
-The relative path must not escape the root directory - if this is attempted, the packaging stage will fail.
-
-Property | Type | Description
---- | --- | ---
-`include` | `string[]` | An array of paths relative to the directory containing this `devcontainer-feature.json`. If the element is a folder, it is copied recursively. Must be prefixed with `.` or `..` to indicate the provided string is relative path.
-
-### Example
-
-```json
-{
- "name": "featureA",
- "version": "0.0.1",
- "include": [
- "../../utils/",
- "../../company-welcome-message.txt"
- ]
-}
-```
-
-## [Proposal B] Change: Structure of packaged Feature
-
-Change the file structure of the packaged Feature to mirror the directory structure of the source code. This will simplify the implementation of **Proposal A** and keep the relative paths consistent before and after packaging.
-
-When running the packaging step, each Feature is packaged separately under `./src/`. Other included directories will be copied into the root of the packaged artifact as indicated in **Proposal A**.
-
-An implementation should resolve the `devcontainer-feature.json` by checking for its presence in the following order of precedence:
-
- - `./src//devcontainer-feature.json`
-- `devcontainer-feature.json`
-
-From here forward, the proposed format will be used during the packaging step. For backwards compatibility, the existing format (with a `devcontainer-feature.json` at the top level) will be supported.
-
-### Example
-
-Given this example repository containing a collection of Features.
-
-```
-.
-├── images
-│ ├── 1.png
-│ ├── 2.png
-├── company-welcome-message.txt
-├── utils
-| ├── common.sh
-│ └── helpers
-│ ├── a.sh
-│ └── ...
-|
-├── src
-│ ├── featureA
-│ │ ├── devcontainer-feature.json
-│ │ ├── install.sh
-│ │ └── ...
-│ ├── featureB
-│ │ ├── devcontainer-feature.json
-│ │ └── install.sh
-│ │ └── ...
-| ├── ...
-│ │ ├── devcontainer-feature.json
-│ │ └── install.sh
-│ │ └── ...
-├── ...
-```
-
-When packaging Feature A (shown above in **Proposal A**), the resulting published archive will be structured as follows:
-
-```
-.
-├── company-welcome-message.txt
-├── utils
-| ├── common.sh
-│ └── helpers
-│ ├── a.sh
-│ └── ...
-|
-├── src
-│ ├── featureA
-│ │ ├── devcontainer-feature.json
-│ │ ├── install.sh
-│ │ └── ...
-```
-
-The packaging step recursively copies the contents of the `utils` folder into the resulting archive. Additionally, the `company-welcome-message.txt` is packaged and distributed with the Feature.
-
-Note that the `images` folder is not included in the packaged Feature. This is because the `images` folder is not included in the `include` property of the `devcontainer-feature.json` file.
-
-#### Using an included script in a Feature
-
-The following example shows how a Feature could include a `utils` folder that contains a `common.sh` file.
-
-```bash
-# utils/common.sh
-function common_function() {
- echo "Hello, '$1'"
-}
-```
-
-```bash
-# src/featureA/install.sh
-
-# Include common functions
-source "../../utils/common.sh"
-
-# Use common function
-common_function "devcontainers"
-```
-
------
-
-# Possible Extensions
-
-This section provides hints to possible future work that could extend the proposal above. These are not part of the proposal, but are provided to help the community understand the potential future impact of this proposal.
-
-## Distributing shared library Features
-
-In an effort to reduce the need for authors to copy/paste auxillary scripts between Feature namespaces, provide the ability to publish "library" Features. These Features would be published [following the Feature distribution spec](https://containers.dev/implementors/features-distribution/#distribution) under a new manifest type.
-
-A "library" can be included in a Feature's `include` property as an alternative to a relative path. By itself, a "library" Feature would not be installable.
-
-```json
-
-{
- "name": "featureA",
- "version": "0.0.1",
- "include": [
- "ghcr.io/devcontainers/features/utils:0.0.1"
- ]
-}
diff --git a/proposals/features-user-env-variables.md b/proposals/features-user-env-variables.md
deleted file mode 100644
index 260a48c9..00000000
--- a/proposals/features-user-env-variables.md
+++ /dev/null
@@ -1,15 +0,0 @@
-## Goal
-
-Feature scripts run as the `root` user and sometimes need to know which user account the dev container will be used with.
-
-(The dev container user can be configured through the `remoteUser` property in the devcontainer.json. If that is not set, the container user will be used.)
-
-## Proposal
-
-Pass `_REMOTE_USER` and `_CONTAINER_USER` environment variables to the features scripts with `_CONTAINER_USER` being the container's user and `_REMOTE_USER` being the configured `remoteUser`. If no `remoteUser` is configured, `_REMOTE_USER` is set to the same value as `_CONTAINER_USER`.
-
-Additionally the home folders of the two users are passed to the feature scripts as `_REMOTE_USER_HOME` and `_CONTAINER_USER_HOME` environment variables.
-
-## Notes
-
-- The container user can be set with `containerUser` in the devcontainer.json and image metadata, `user` in the docker-compose.yml, `USER` in the Dockerfile and can be passed down from the base image.
diff --git a/proposals/gpu-host-requirement.md b/proposals/gpu-host-requirement.md
deleted file mode 100644
index 7c47176d..00000000
--- a/proposals/gpu-host-requirement.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# GPU host requirement
-
-## Goal
-
-This proposal adds GPU support to the existing host requirements properties.
-- Issue: https://github.com/devcontainers/spec/issues/82
-- Community PR: https://github.com/devcontainers/cli/pull/173
-
-## Proposal
-
-We propose to add a new `gpu` property to the `hostRequirements` object in the devcontainer.json schema. The property can be a boolean value, the string `optional` or an object:
-
-(Additional row for the existing table in the spec.)
-| Property | Type | Description |
-|----------|------|-------------|
-| `hostRequirements.gpu` 🏷️ | boolean \| 'optional' | Indicates whether or not a GPU is required. A value 'optional' indicates that might be used if available. The object is described in the table below. The default is false. For example: `"hostRequirements": "optional"` |
-
-The object value can have the following properties:
-
-| Property | Type | Description |
-|----------|------|-------------|
-| `hostRequirements.gpu.cores` 🏷️ | integer | Indicates the minimum required number of cores. For example: `"hostRequirements": { "gpu": {"cores": 2} }` |
-| `hostRequirements.gpu.memory` 🏷️ | string | A string indicating minimum memory requirements with a `tb`, `gb`, `mb`, or `kb` suffix. For example, `"hostRequirements": {"memory": "4gb"}` |
diff --git a/proposals/image-metadata.md b/proposals/image-metadata.md
deleted file mode 100644
index 454086b4..00000000
--- a/proposals/image-metadata.md
+++ /dev/null
@@ -1,87 +0,0 @@
-# Image Metadata
-
-## Goal
-
-Record dev container config and feature metadata in prebuilt images, such that, the image and the built-in features can be used with a devcontainer.json (image-, Dockerfile- or Docker Compose-based) that does not repeat the dev container config or feature metadata. Other tools should be able to record the same metadata without necessarily using features themselves.
-
-Current dev container config that can be recorded in the image: `mounts`, `onCreateCommand`, `updateContentCommand`, `postCreateCommand`, `postStartCommand`, `postAttachCommand`, `customizations`, `remoteUser`, `userEnvProbe`, `remoteEnv`, `containerEnv`, `overrideCommand`, `portsAttributes`, `otherPortsAttributes`, `forwardPorts`, `shutdownAction`, `updateRemoteUserUID` and `hostRequirements`.
-
-Current feature metadata relevant for using the feature when it is already part of the image: `mounts`, `init`, `privileged`, `capAdd`, `securityOpt`, `entrypoint` and `customizations`.
-
-We can add to these lists as we add more properties to the dev container configuration and the feature metadata.
-
-## Proposal
-
-We propose to add metadata to the image with the following structure using one entry per feature and devcontainer.json (see table below for the full list):
-
-```
-[
- {
- "id"?: string,
- "init"?: boolean,
- "privileged"?: boolean,
- "capAdd"?: string[],
- "securityOpt"?: string[],
- "entrypoint"?: string,
- "mounts"?: [],
- ...
- "customizations"?: {
- ...
- }
- },
- ...
-]
-```
-
-To simplify adding this metadata for other tools, we also support having a single top-level object with the same properties.
-
-The metadata is added to the image as a `devcontainer.metadata` label with a JSON string value representing the above array or single object.
-
-## Merge Logic
-
-To apply the metadata together with a user's devcontainer.json at runtime the following merge logic by property is used. The table also notes which properties are currently supported coming from the devcontainer.json and which from the feature metadata, this will change over time as we add more properties.
-
-| Property | Type/Format | Merge Logic | devcontainer.json | Feature Metadata |
-| -------- | ----------- | ----------- | :---------------: | :--------------: |
-| `id` | E.g., `ghcr.io/devcontainers/features/node:1` | Not merged. | | x |
-| `init` | `boolean` | `true` if at least one is `true`, `false` otherwise. | x | x |
-| `privileged` | `boolean` | `true` if at least one is `true`, `false` otherwise. | x | x |
-| `capAdd` | `string[]` | Union of all `capAdd` arrays without duplicates. | x | x |
-| `securityOpt` | `string[]` | Union of all `securityOpt` arrays without duplicates. | x | x |
-| `entrypoint` | `string` | Collected list of all entrypoints. | | x |
-| `mounts` | `(string \| { type, src, dst })[]` | Collected list of all mountpoints. Conflicts: Last source wins. | x | x |
-| `onCreateCommand` | `string \| string[]` | Collected list of all onCreateCommands. | x | |
-| `updateContentCommand` | `string \| string[]` | Collected list of all updateContentCommands. | x | |
-| `postCreateCommand` | `string \| string[]` | Collected list of all postCreateCommands. | x | |
-| `postStartCommand` | `string \| string[]` | Collected list of all postStartCommands. | x | |
-| `postAttachCommand` | `string \| string[]` | Collected list of all postAttachCommands. | x | |
-| `waitFor` | enum | Last value wins. | x | |
-| `customizations` | Object of tool-specific customizations. | Merging is left to the tools. | x | x |
-| `containerUser` | `string` | Last value wins. | x | |
-| `remoteUser` | `string` | Last value wins. | x | |
-| `userEnvProbe` | `string` (enum) | Last value wins. | x | |
-| `remoteEnv` | Object of strings. | Per variable, last value wins. | x | |
-| `containerEnv` | Object of strings. | Per variable, last value wins. | x | |
-| `overrideCommand` | `boolean` | Last value wins. | x | |
-| `portsAttributes` | Map of ports to attributes. | Per port (not per port attribute), last value wins. | x | |
-| `otherPortsAttributes` | Port attributes. | Last value wins (not per port attribute). | x | |
-| `forwardPorts` | `(number \| string)[]` | Union of all ports without duplicates. Last one wins (when mapping changes). | x | |
-| `shutdownAction` | `string` (enum) | Last value wins. | x | |
-| `updateRemoteUserUID` | `boolean` | Last value wins. | x | |
-| `hostRequirements` | `cpus`, `memory`, `storage` | Max value wins. | x | |
-
-Variables in string values will be substituted at the time the value is applied. When the order matters, the devcontainer.json is considered last.
-
-## Additional devcontainer.json Properties
-
-We are adding support for `mounts`, `containerEnv`, `containerUser`, `init`, `privileged`, `capAdd`, and `securityOpt` to the devcontainer.json (also with Docker Compose) the same way these properties are already supported in the feature metadata.
-
-## Notes
-
-- Passing the label as a `LABEL` instruction in the Dockerfile:
- - The size limit on Dockerfiles is around 1.3MB. The line length is limited to 65k characters.
- - Using one line per feature should allow for making full use of these limits.
-- Passing the label as a command line argument:
- - There is no size limit documented for labels, but the daemon returns an error when the request header is >500kb.
- - The 500kb limit is shared, so we cannot use a second label in the same build to avoid it.
- - If/when this becomes an issue we could embed the metadata as a file in the image (e.g., with a label indicating it).
diff --git a/proposals/parallel-lifecycle-script-execution.md b/proposals/parallel-lifecycle-script-execution.md
deleted file mode 100644
index e5f2b218..00000000
--- a/proposals/parallel-lifecycle-script-execution.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# Parallel lifecycle script execution
-
-Support executing multiple lifecycle scripts in parallel by providing them in `object` form.
-
-## Motivation
-
-Devcontainers supports a single command for each of its lifecycle scripts. While serial execution of multiple commands can be achieved with `;`, `&&`, etc. parallel is less straightforward and so deserves first-class support.
-
-## Spec changes
-
-All lifecycle scripts will be extended to support `object` types. The key of the `object` will be a unique name for the command and the value will be the `string` or `array` command. Each command must exit successfully for the stage to be considered successful.
-
-Each entry in the `object` will be run in parallel during that lifecycle step.
-
-### Example
-
-```json
-{
- "postCreateCommand": {
- "server": "npm start",
- "db": ["mysql", "-u", "root", "-p", "my database"]
- }
-}
-```
diff --git a/proposals/secrets-support.md b/proposals/secrets-support.md
deleted file mode 100644
index 5aeb7ae5..00000000
--- a/proposals/secrets-support.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# First class secrets support in dev containers implementations
-
-## What are secrets
-Secrets are variables that hold sensitive values and need to be handled securely at all times (API keys, passwords etc.). Users can change a secret's value at any time, and a conforming dev containers implementation should support dynamically changing secrets without having to rebuild the container.
-
-## Goal
-
-Support secrets as a first class feature in dev containers implementations.
-
-This feature should consist of the ability to securely pass in the secrets, make them available for users to consume similar to remoteEnv and containerEnv, and be processed and handled securely at all times.
-This functionality will allow consumers to be able to use secrets more predictably and securely with their dev containers implementation.
-
-## Motivation
-
-Today many consumers pass secret variables as `remoteEnv`, since there are no other mechanisms to pass them explicitly as secrets. The dev containers reference implementation do not (and need not) treat `remoteEnv` as secrets. Having explicit support for secrets will help eliminate security threats such as leaking secrets, as well as in improving customer confidence.
-
-## Proposal
-
-A [supporting tool](https://containers.dev/supporting#tools) (ie, for example the [dev container CLI reference implementation](https://github.com/devcontainers/cli)) should behave according to the following properties:
-
- 1. Ability to pass secrets to commands
- 2. Apply/use secrets similar to `remoteEnv`
- 3. Securely handle secrets
-
-### Passing secrets in
-Secrets are not part of dev containers specification and we do not expect users to store secrets inside `devcontainer.json` file. A conforming implementation should provide a secure mechanism to pass secrets, such as a secrets file, Windows credential manager, Mac keychain, Azure keyvault etc. for example.
-
-#### **Example**
-
-Using a file to pass in the secrets can be one of the simple approaches to adopt. In this example the supporting tool can input secrets in a JSON file format.
-
- ```json
- {
- "API_KEY": "adsjhsd6dfwdjfwde7edwfwedfdjedwf7wedfwe",
- "NUGET_CONFIG": "\n \n \n",
- "PASSWORD": "Simple Passwords"
- }
- ```
diff --git a/schemas/devContainer.base.schema.json b/schemas/devContainer.base.schema.json
deleted file mode 100644
index 33e222a5..00000000
--- a/schemas/devContainer.base.schema.json
+++ /dev/null
@@ -1,741 +0,0 @@
-{
- "$schema": "https://json-schema.org/draft/2019-09/schema",
- "description": "Defines a dev container",
- "allowComments": true,
- "allowTrailingCommas": false,
- "definitions": {
- "devContainerCommon": {
- "type": "object",
- "properties": {
- "$schema": {
- "type": "string",
- "format": "uri",
- "description": "The JSON schema of the `devcontainer.json` file."
- },
- "name": {
- "type": "string",
- "description": "A name for the dev container which can be displayed to the user."
- },
- "features": {
- "type": "object",
- "description": "Features to add to the dev container.",
- "properties": {
- "fish": {
- "deprecated": true,
- "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements."
- },
- "maven": {
- "deprecated": true,
- "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements. E.g., `ghcr.io/devcontainers/features/java` has an option to install Maven."
- },
- "gradle": {
- "deprecated": true,
- "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements. E.g., `ghcr.io/devcontainers/features/java` has an option to install Gradle."
- },
- "homebrew": {
- "deprecated": true,
- "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements."
- },
- "jupyterlab": {
- "deprecated": true,
- "deprecationMessage": "Legacy feature will be removed in the future. Please check https://containers.dev/features for replacements. E.g., `ghcr.io/devcontainers/features/python` has an option to install JupyterLab."
- }
- },
- "additionalProperties": true
- },
- "overrideFeatureInstallOrder": {
- "type": "array",
- "description": "Array consisting of the Feature id (without the semantic version) of Features in the order the user wants them to be installed.",
- "items": {
- "type": "string"
- }
- },
- "forwardPorts": {
- "type": "array",
- "description": "Ports that are forwarded from the container to the local machine. Can be an integer port number, or a string of the format \"host:port_number\".",
- "items": {
- "oneOf": [
- {
- "type": "integer",
- "maximum": 65535,
- "minimum": 0
- },
- {
- "type": "string",
- "pattern": "^([a-z0-9-]+):(\\d{1,5})$"
- }
- ]
- }
- },
- "portsAttributes": {
- "type": "object",
- "patternProperties": {
- "(^\\d+(-\\d+)?$)|(.+)": {
- "type": "object",
- "description": "A port, range of ports (ex. \"40000-55000\"), or regular expression (ex. \".+\\\\/server.js\"). For a port number or range, the attributes will apply to that port number or range of port numbers. Attributes which use a regular expression will apply to ports whose associated process command line matches the expression.",
- "properties": {
- "onAutoForward": {
- "type": "string",
- "enum": [
- "notify",
- "openBrowser",
- "openBrowserOnce",
- "openPreview",
- "silent",
- "ignore"
- ],
- "enumDescriptions": [
- "Shows a notification when a port is automatically forwarded.",
- "Opens the browser when the port is automatically forwarded. Depending on your settings, this could open an embedded browser.",
- "Opens the browser when the port is automatically forwarded, but only the first time the port is forward during a session. Depending on your settings, this could open an embedded browser.",
- "Opens a preview in the same window when the port is automatically forwarded.",
- "Shows no notification and takes no action when this port is automatically forwarded.",
- "This port will not be automatically forwarded."
- ],
- "description": "Defines the action that occurs when the port is discovered for automatic forwarding",
- "default": "notify"
- },
- "elevateIfNeeded": {
- "type": "boolean",
- "description": "Automatically prompt for elevation (if needed) when this port is forwarded. Elevate is required if the local port is a privileged port.",
- "default": false
- },
- "label": {
- "type": "string",
- "description": "Label that will be shown in the UI for this port.",
- "default": "Application"
- },
- "requireLocalPort": {
- "type": "boolean",
- "markdownDescription": "When true, a modal dialog will show if the chosen local port isn't used for forwarding.",
- "default": false
- },
- "protocol": {
- "type": "string",
- "enum": [
- "http",
- "https"
- ],
- "description": "The protocol to use when forwarding this port."
- }
- },
- "default": {
- "label": "Application",
- "onAutoForward": "notify"
- }
- }
- },
- "markdownDescription": "Set default properties that are applied when a specific port number is forwarded. For example:\n\n```\n\"3000\": {\n \"label\": \"Application\"\n},\n\"40000-55000\": {\n \"onAutoForward\": \"ignore\"\n},\n\".+\\\\/server.js\": {\n \"onAutoForward\": \"openPreview\"\n}\n```",
- "defaultSnippets": [
- {
- "body": {
- "${1:3000}": {
- "label": "${2:Application}",
- "onAutoForward": "notify"
- }
- }
- }
- ],
- "additionalProperties": false
- },
- "otherPortsAttributes": {
- "type": "object",
- "properties": {
- "onAutoForward": {
- "type": "string",
- "enum": [
- "notify",
- "openBrowser",
- "openPreview",
- "silent",
- "ignore"
- ],
- "enumDescriptions": [
- "Shows a notification when a port is automatically forwarded.",
- "Opens the browser when the port is automatically forwarded. Depending on your settings, this could open an embedded browser.",
- "Opens a preview in the same window when the port is automatically forwarded.",
- "Shows no notification and takes no action when this port is automatically forwarded.",
- "This port will not be automatically forwarded."
- ],
- "description": "Defines the action that occurs when the port is discovered for automatic forwarding",
- "default": "notify"
- },
- "elevateIfNeeded": {
- "type": "boolean",
- "description": "Automatically prompt for elevation (if needed) when this port is forwarded. Elevate is required if the local port is a privileged port.",
- "default": false
- },
- "label": {
- "type": "string",
- "description": "Label that will be shown in the UI for this port.",
- "default": "Application"
- },
- "requireLocalPort": {
- "type": "boolean",
- "markdownDescription": "When true, a modal dialog will show if the chosen local port isn't used for forwarding.",
- "default": false
- },
- "protocol": {
- "type": "string",
- "enum": [
- "http",
- "https"
- ],
- "description": "The protocol to use when forwarding this port."
- }
- },
- "defaultSnippets": [
- {
- "body": {
- "onAutoForward": "ignore"
- }
- }
- ],
- "markdownDescription": "Set default properties that are applied to all ports that don't get properties from the setting `remote.portsAttributes`. For example:\n\n```\n{\n \"onAutoForward\": \"ignore\"\n}\n```",
- "additionalProperties": false
- },
- "updateRemoteUserUID": {
- "type": "boolean",
- "description": "Controls whether on Linux the container's user should be updated with the local user's UID and GID. On by default when opening from a local folder."
- },
- "containerEnv": {
- "type": "object",
- "additionalProperties": {
- "type": "string"
- },
- "description": "Container environment variables."
- },
- "containerUser": {
- "type": "string",
- "description": "The user the container will be started with. The default is the user on the Docker image."
- },
- "mounts": {
- "type": "array",
- "description": "Mount points to set up when creating the container. See Docker's documentation for the --mount option for the supported syntax.",
- "items": {
- "anyOf": [
- {
- "$ref": "#/definitions/Mount"
- },
- {
- "type": "string"
- }
- ]
- }
- },
- "init": {
- "type": "boolean",
- "description": "Passes the --init flag when creating the dev container."
- },
- "privileged": {
- "type": "boolean",
- "description": "Passes the --privileged flag when creating the dev container."
- },
- "capAdd": {
- "type": "array",
- "description": "Passes docker capabilities to include when creating the dev container.",
- "examples": [
- "SYS_PTRACE"
- ],
- "items": {
- "type": "string"
- }
- },
- "securityOpt": {
- "type": "array",
- "description": "Passes docker security options to include when creating the dev container.",
- "examples": [
- "seccomp=unconfined"
- ],
- "items": {
- "type": "string"
- }
- },
- "remoteEnv": {
- "type": "object",
- "additionalProperties": {
- "type": [
- "string",
- "null"
- ]
- },
- "description": "Remote environment variables to set for processes spawned in the container including lifecycle scripts and any remote editor/IDE server process."
- },
- "remoteUser": {
- "type": "string",
- "description": "The username to use for spawning processes in the container including lifecycle scripts and any remote editor/IDE server process. The default is the same user as the container."
- },
- "initializeCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
- "description": "A command to run locally (i.e Your host machine, cloud VM) before anything else. This command is run before \"onCreateCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
- "items": {
- "type": "string"
- },
- "additionalProperties": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
- }
- },
- "onCreateCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
- "description": "A command to run when creating the container. This command is run after \"initializeCommand\" and before \"updateContentCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
- "items": {
- "type": "string"
- },
- "additionalProperties": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
- }
- },
- "updateContentCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
- "description": "A command to run when creating the container and rerun when the workspace content was updated while creating the container. This command is run after \"onCreateCommand\" and before \"postCreateCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
- "items": {
- "type": "string"
- },
- "additionalProperties": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
- }
- },
- "postCreateCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
- "description": "A command to run after creating the container. This command is run after \"updateContentCommand\" and before \"postStartCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
- "items": {
- "type": "string"
- },
- "additionalProperties": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
- }
- },
- "postStartCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
- "description": "A command to run after starting the container. This command is run after \"postCreateCommand\" and before \"postAttachCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
- "items": {
- "type": "string"
- },
- "additionalProperties": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
- }
- },
- "postAttachCommand": {
- "type": [
- "string",
- "array",
- "object"
- ],
- "description": "A command to run when attaching to the container. This command is run after \"postStartCommand\". If this is a single string, it will be run in a shell. If this is an array of strings, it will be run as a single command without shell. If this is an object, each provided command will be run in parallel.",
- "items": {
- "type": "string"
- },
- "additionalProperties": {
- "type": [
- "string",
- "array"
- ],
- "items": {
- "type": "string"
- }
- }
- },
- "waitFor": {
- "type": "string",
- "enum": [
- "initializeCommand",
- "onCreateCommand",
- "updateContentCommand",
- "postCreateCommand",
- "postStartCommand"
- ],
- "description": "The user command to wait for before continuing execution in the background while the UI is starting up. The default is \"updateContentCommand\"."
- },
- "userEnvProbe": {
- "type": "string",
- "enum": [
- "none",
- "loginShell",
- "loginInteractiveShell",
- "interactiveShell"
- ],
- "description": "User environment probe to run. The default is \"loginInteractiveShell\"."
- },
- "hostRequirements": {
- "type": "object",
- "description": "Host hardware requirements.",
- "properties": {
- "cpus": {
- "type": "integer",
- "minimum": 1,
- "description": "Number of required CPUs."
- },
- "memory": {
- "type": "string",
- "pattern": "^\\d+([tgmk]b)?$",
- "description": "Amount of required RAM in bytes. Supports units tb, gb, mb and kb."
- },
- "storage": {
- "type": "string",
- "pattern": "^\\d+([tgmk]b)?$",
- "description": "Amount of required disk space in bytes. Supports units tb, gb, mb and kb."
- },
- "gpu": {
- "oneOf": [
- {
- "type": [
- "boolean",
- "string"
- ],
- "enum": [
- true,
- false,
- "optional"
- ],
- "description": "Indicates whether a GPU is required. The string \"optional\" indicates that a GPU is optional. An object value can be used to configure more detailed requirements."
- },
- {
- "type": "object",
- "properties": {
- "cores": {
- "type": "integer",
- "minimum": 1,
- "description": "Number of required cores."
- },
- "memory": {
- "type": "string",
- "pattern": "^\\d+([tgmk]b)?$",
- "description": "Amount of required RAM in bytes. Supports units tb, gb, mb and kb."
- }
- },
- "description": "Indicates whether a GPU is required. The string \"optional\" indicates that a GPU is optional. An object value can be used to configure more detailed requirements.",
- "additionalProperties": false
- }
- ]
- }
- },
- "unevaluatedProperties": false
- },
- "customizations": {
- "type": "object",
- "description": "Tool-specific configuration. Each tool should use a JSON object subproperty with a unique name to group its customizations."
- },
- "additionalProperties": {
- "type": "object",
- "additionalProperties": true
- }
- }
- },
- "nonComposeBase": {
- "type": "object",
- "properties": {
- "appPort": {
- "type": [
- "integer",
- "string",
- "array"
- ],
- "description": "Application ports that are exposed by the container. This can be a single port or an array of ports. Each port can be a number or a string. A number is mapped to the same port on the host. A string is passed to Docker unchanged and can be used to map ports differently, e.g. \"8000:8010\".",
- "items": {
- "type": [
- "integer",
- "string"
- ]
- }
- },
- "runArgs": {
- "type": "array",
- "description": "The arguments required when starting in the container.",
- "items": {
- "type": "string"
- }
- },
- "shutdownAction": {
- "type": "string",
- "enum": [
- "none",
- "stopContainer"
- ],
- "description": "Action to take when the user disconnects from the container in their editor. The default is to stop the container."
- },
- "overrideCommand": {
- "type": "boolean",
- "description": "Whether to overwrite the command specified in the image. The default is true."
- },
- "workspaceFolder": {
- "type": "string",
- "description": "The path of the workspace folder inside the container."
- },
- "workspaceMount": {
- "type": "string",
- "description": "The --mount parameter for docker run. The default is to mount the project folder at /workspaces/$project."
- }
- }
- },
- "dockerfileContainer": {
- "oneOf": [
- {
- "type": "object",
- "properties": {
- "build": {
- "type": "object",
- "description": "Docker build-related options.",
- "allOf": [
- {
- "type": "object",
- "properties": {
- "dockerfile": {
- "type": "string",
- "description": "The location of the Dockerfile that defines the contents of the container. The path is relative to the folder containing the `devcontainer.json` file."
- },
- "context": {
- "type": "string",
- "description": "The location of the context folder for building the Docker image. The path is relative to the folder containing the `devcontainer.json` file."
- }
- },
- "required": [
- "dockerfile"
- ]
- },
- {
- "$ref": "#/definitions/buildOptions"
- }
- ],
- "unevaluatedProperties": false
- }
- },
- "required": [
- "build"
- ]
- },
- {
- "allOf": [
- {
- "type": "object",
- "properties": {
- "dockerFile": {
- "type": "string",
- "description": "The location of the Dockerfile that defines the contents of the container. The path is relative to the folder containing the `devcontainer.json` file."
- },
- "context": {
- "type": "string",
- "description": "The location of the context folder for building the Docker image. The path is relative to the folder containing the `devcontainer.json` file."
- }
- },
- "required": [
- "dockerFile"
- ]
- },
- {
- "type": "object",
- "properties": {
- "build": {
- "description": "Docker build-related options.",
- "$ref": "#/definitions/buildOptions"
- }
- }
- }
- ]
- }
- ]
- },
- "buildOptions": {
- "type": "object",
- "properties": {
- "target": {
- "type": "string",
- "description": "Target stage in a multi-stage build."
- },
- "args": {
- "type": "object",
- "additionalProperties": {
- "type": [
- "string"
- ]
- },
- "description": "Build arguments."
- },
- "cacheFrom": {
- "type": [
- "string",
- "array"
- ],
- "description": "The image to consider as a cache. Use an array to specify multiple images.",
- "items": {
- "type": "string"
- }
- }
- }
- },
- "imageContainer": {
- "type": "object",
- "properties": {
- "image": {
- "type": "string",
- "description": "The docker image that will be used to create the container."
- }
- },
- "required": [
- "image"
- ]
- },
- "composeContainer": {
- "type": "object",
- "properties": {
- "dockerComposeFile": {
- "type": [
- "string",
- "array"
- ],
- "description": "The name of the docker-compose file(s) used to start the services.",
- "items": {
- "type": "string"
- }
- },
- "service": {
- "type": "string",
- "description": "The service you want to work on. This is considered the primary container for your dev environment which your editor will connect to."
- },
- "runServices": {
- "type": "array",
- "description": "An array of services that should be started and stopped.",
- "items": {
- "type": "string"
- }
- },
- "workspaceFolder": {
- "type": "string",
- "description": "The path of the workspace folder inside the container. This is typically the target path of a volume mount in the docker-compose.yml."
- },
- "shutdownAction": {
- "type": "string",
- "enum": [
- "none",
- "stopCompose"
- ],
- "description": "Action to take when the user disconnects from the primary container in their editor. The default is to stop all of the compose containers."
- },
- "overrideCommand": {
- "type": "boolean",
- "description": "Whether to overwrite the command specified in the image. The default is false."
- }
- },
- "required": [
- "dockerComposeFile",
- "service",
- "workspaceFolder"
- ]
- },
- "Mount": {
- "type": "object",
- "properties": {
- "type": {
- "type": "string",
- "enum": [
- "bind",
- "volume"
- ],
- "description": "Mount type."
- },
- "source": {
- "type": "string",
- "description": "Mount source."
- },
- "target": {
- "type": "string",
- "description": "Mount target."
- }
- },
- "required": [
- "type",
- "source",
- "target"
- ],
- "additionalProperties": false
- }
- },
- "oneOf": [
- {
- "allOf": [
- {
- "oneOf": [
- {
- "allOf": [
- {
- "oneOf": [
- {
- "$ref": "#/definitions/dockerfileContainer"
- },
- {
- "$ref": "#/definitions/imageContainer"
- }
- ]
- },
- {
- "$ref": "#/definitions/nonComposeBase"
- }
- ]
- },
- {
- "$ref": "#/definitions/composeContainer"
- }
- ]
- },
- {
- "$ref": "#/definitions/devContainerCommon"
- }
- ]
- },
- {
- "type": "object",
- "$ref": "#/definitions/devContainerCommon",
- "additionalProperties": false
- }
- ],
- "unevaluatedProperties": false
-}
\ No newline at end of file
diff --git a/schemas/devContainer.schema.json b/schemas/devContainer.schema.json
deleted file mode 100644
index 652f1bf9..00000000
--- a/schemas/devContainer.schema.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "allOf": [
- {
- "$ref": "./devContainer.base.schema.json"
- },
- {
- "$ref": "https://raw.githubusercontent.com/microsoft/vscode/main/extensions/configuration-editing/schemas/devContainer.codespaces.schema.json"
- },
- {
- "$ref": "https://raw.githubusercontent.com/microsoft/vscode/main/extensions/configuration-editing/schemas/devContainer.vscode.schema.json"
- }
- ]
-}