base on A reference implementation for the specification that can create and configure a dev container from a devcontainer.json. # Dev Container CLI This repository holds the dev container CLI, which can take a devcontainer.json and create and configure a dev container from it. ## Context 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. Dev containers can be run locally or remotely, in a private or public cloud. ![Diagram of inner and outerloop development with dev containers](/images/dev-container-stages.png) This CLI is in active development. Current status: - [x] `devcontainer build` - Enables building/pre-building images - [x] `devcontainer up` - Spins up containers with `devcontainer.json` settings applied - [x] `devcontainer run-user-commands` - Runs lifecycle commands like `postCreateCommand` - [x] `devcontainer read-configuration` - Outputs current configuration for workspace - [x] `devcontainer exec` - Executes a command in a container with `userEnvProbe`, `remoteUser`, `remoteEnv`, and other properties applied - [x] `devcontainer features <...>` - Tools to assist in authoring and testing [Dev Container Features](https://containers.dev/implementors/features/) - [x] `devcontainer templates <...>` - Tools to assist in authoring and testing [Dev Container Templates](https://containers.dev/implementors/templates/) - [ ] `devcontainer stop` - Stops containers - [ ] `devcontainer down` - Stops and deletes containers ## Try it out We'd love for you to try out the dev container CLI and let us know what you think. You can quickly try it out in just a few simple steps, either by using the install script, installing its npm package, or building the CLI repo from sources (see "[Build from sources](#build-from-sources)"). ### Install script You can install the CLI with a standalone script that downloads a bundled Node.js runtime, so no pre-installed Node.js is required. It works on Linux and macOS (x64 and arm64): ```bash curl -fsSL https://raw.githubusercontent.com/devcontainers/cli/main/scripts/install.sh | sh ``` Then add the install location to your PATH: ```bash export PATH="$HOME/.devcontainers/bin:$PATH" ``` You can also specify a version, a custom install directory, or update/uninstall an existing installation: ```bash # Install a specific version sh install.sh --version 0.82.0 # Install to a custom directory sh install.sh --prefix ~/.local/devcontainers # Update to latest sh install.sh --update # Uninstall sh install.sh --uninstall ``` ### npm install To install the npm package you will need Python and C/C++ installed to build one of the dependencies (see, e.g., [here](https://github.com/microsoft/vscode/wiki/How-to-Contribute) for instructions). ```bash npm install -g @devcontainers/cli ``` Verify you can run the CLI and see its help text: ```bash devcontainer <command> Commands: devcontainer up Create and run dev container devcontainer build [path] Build a dev container image devcontainer run-user-commands Run user commands devcontainer read-configuration Read configuration devcontainer features Features commands devcontainer templates Templates commands devcontainer exec <cmd> [args..] Execute a command on a running dev container Options: --help Show help [boolean] --version Show version number [boolean] ``` ### Try out the CLI Once you have the CLI, you can try it out with a sample project, like this [Rust sample](https://github.com/microsoft/vscode-remote-try-rust). Clone the Rust sample to your machine, and start a dev container with the CLI's `up` command: ```bash git clone https://github.com/microsoft/vscode-remote-try-rust devcontainer up --workspace-folder <path-to-vscode-remote-try-rust> ``` This will download the container image from a container registry and start the container. Your Rust container should now be running: ```bash [88 ms] dev-containers-cli 0.1.0. [165 ms] Start: Run: docker build -f /home/node/vscode-remote-try-rust/.devcontainer/Dockerfile -t vsc-vscode-remote-try-rust-89420ad7399ba74f55921e49cc3ecfd2 --build-arg VARIANT=bullseye /home/node/vscode-remote-try-rust/.devcontainer [+] Building 0.5s (5/5) FINISHED => [internal] load build definition from Dockerfile 0.0s => => transferring dockerfile: 38B 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load metadata for mcr.microsoft.com/vscode/devcontainers/r 0.4s => CACHED [1/1] FROM mcr.microsoft.com/vscode/devcontainers/rust:1-bulls 0.0s => exporting to image 0.0s => => exporting layers 0.0s => => writing image sha256:39873ccb81e6fb613975e11e37438eee1d49c963a436d 0.0s => => naming to docker.io/library/vsc-vscode-remote-try-rust-89420ad7399 0.0s [1640 ms] Start: Run: docker run --sig-proxy=false -a STDOUT -a STDERR --mount type=bind,source=/home/node/vscode-remote-try-rust,target=/workspaces/vscode-remote-try-rust -l devcontainer.local_folder=/home/node/vscode-remote-try-rust --cap-add=SYS_PTRACE --security-opt seccomp=unconfined --entrypoint /bin/sh vsc-vscode-remote-try-rust-89420ad7399ba74f55921e49cc3ecfd2-uid -c echo Container started Container started {"outcome":"success","containerId":"f0a055ff056c1c1bb99cc09930efbf3a0437c54d9b4644695aa23c1d57b4bd11","remoteUser":"vscode","remoteWorkspaceFolder":"/workspaces/vscode-remote-try-rust"} ``` You can then run commands in this dev container: ```bash devcontainer exec --workspace-folder <path-to-vscode-remote-try-rust> cargo run ``` This will compile and run the Rust sample, outputting: ```bash [33 ms] dev-containers-cli 0.1.0. Compiling hello_remote_world v0.1.0 (/workspaces/vscode-remote-try-rust) Finished dev [unoptimized + debuginfo] target(s) in 1.06s Running `target/debug/hello_remote_world` Hello, VS Code Remote - Containers! {"outcome":"success"} ``` Congrats, you've just run the dev container CLI and seen it in action! ## More CLI examples The [example-usage](./example-usage) folder contains some simple shell scripts to illustrate how the CLI can be used to: - Inject tools for use inside a development container - Use a dev container as your CI build environment to build an application (even if it is not deployed as a container) - Build a container image from a devcontainer.json file that includes [dev container features](https://containers.dev/implementors/features/#devcontainer-json-properties) ## Build from sources This repository has a [dev container configuration](https://github.com/devcontainers/cli/tree/main/.devcontainer), which you can use to ensure you have the right dependencies installed. Compile the CLI with yarn: ```sh yarn yarn compile ``` Verify you can run the CLI and see its help text: ```sh node devcontainer.js --help ``` ## Specification The dev container CLI is part of the [Development Containers Specification](https://github.com/devcontainers/spec). This spec 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. Learn more on the [dev container spec website](https://devcontainers.github.io/). ## Additional resources You may review other resources part of the specification in the [`devcontainers` GitHub organization](https://github.com/devcontainers). ### Documentation - Additional information on using the built-in [Features testing command](./docs/features/test.md). ## Contributing Check out how to contribute to the CLI in [CONTRIBUTING.md](CONTRIBUTING.md). ## License This project is under an [MIT license](LICENSE.txt). ", Assign "at most 3 tags" to the expected json: {"id":"10191","tags":[]} "only from the tags list I provide: [{"id":39,"name":"3d-generation","display_name":"3D generation","slug":"3d-generation"},{"id":3,"name":"ai-agent","display_name":"AI agent","slug":"ai-agent"},{"id":8,"name":"ai-coding","display_name":"AI coding assistant","slug":"ai-coding"},{"id":5,"name":"ai-image","display_name":"AI image generation","slug":"ai-image"},{"id":9,"name":"ai-infrastructure","display_name":"AI infrastructure","slug":"ai-infrastructure"},{"id":10,"name":"ai-memory","display_name":"AI memory","slug":"ai-memory"},{"id":11,"name":"ai-skills","display_name":"AI skills","slug":"ai-skills"},{"id":12,"name":"ai-translation","display_name":"AI translation","slug":"ai-translation"},{"id":6,"name":"ai-video","display_name":"AI video generation","slug":"ai-video"},{"id":4,"name":"ai-voice","display_name":"AI voice","slug":"ai-voice"},{"id":7,"name":"ai-workflow","display_name":"AI workflow","slug":"ai-workflow"},{"id":22,"name":"audio-processing","display_name":"Audio processing","slug":"audio-processing"},{"id":29,"name":"authentication","display_name":"Authentication","slug":"authentication"},{"id":51,"name":"bundler","display_name":"Bundler","slug":"bundler"},{"id":41,"name":"chatbot","display_name":"Chatbot","slug":"chatbot"},{"id":27,"name":"cloud-native","display_name":"Cloud native","slug":"cloud-native"},{"id":1,"name":"computer-vision","display_name":"Computer vision","slug":"computer-vision"},{"id":37,"name":"crypto-trading","display_name":"Crypto trading","slug":"crypto-trading"},{"id":57,"name":"curated-list","display_name":"Curated list","slug":"curated-list"},{"id":54,"name":"data-streaming","display_name":"Data streaming","slug":"data-streaming"},{"id":35,"name":"data-visualization","display_name":"Data visualization","slug":"data-visualization"},{"id":16,"name":"database-backup","display_name":"Database backup","slug":"database-backup"},{"id":49,"name":"design-system","display_name":"Design system","slug":"design-system"},{"id":38,"name":"digital-human","display_name":"Digital human","slug":"digital-human"},{"id":34,"name":"document-processing","display_name":"Document processing","slug":"document-processing"},{"id":44,"name":"ecommerce","display_name":"E-commerce","slug":"ecommerce"},{"id":45,"name":"emulator","display_name":"Emulator","slug":"emulator"},{"id":46,"name":"file-management","display_name":"File management","slug":"file-management"},{"id":32,"name":"fintech","display_name":"Fintech","slug":"fintech"},{"id":31,"name":"game-development","display_name":"Game development","slug":"game-development"},{"id":24,"name":"headless-browser","display_name":"Headless browser","slug":"headless-browser"},{"id":52,"name":"headless-cms","display_name":"Headless CMS","slug":"headless-cms"},{"id":36,"name":"home-automation","display_name":"Home automation","slug":"home-automation"},{"id":20,"name":"image-editing","display_name":"Image editing","slug":"image-editing"},{"id":28,"name":"iot","display_name":"IoT","slug":"iot"},{"id":13,"name":"local-llm","display_name":"Local LLM","slug":"local-llm"},{"id":17,"name":"mcp","display_name":"MCP","slug":"mcp"},{"id":47,"name":"monitoring","display_name":"Monitoring","slug":"monitoring"},{"id":2,"name":"nlp","display_name":"NLP","slug":"nlp"},{"id":26,"name":"observability","display_name":"Observability","slug":"observability"},{"id":40,"name":"pentesting","display_name":"Pentesting","slug":"pentesting"},{"id":48,"name":"programming-examples","display_name":"Programming examples","slug":"programming-examples"},{"id":42,"name":"proxy","display_name":"Proxy","slug":"proxy"},{"id":14,"name":"rag","display_name":"RAG","slug":"rag"},{"id":56,"name":"resume-building","display_name":"Resume building","slug":"resume-building"},{"id":33,"name":"robotics","display_name":"Robotics","slug":"robotics"},{"id":30,"name":"search","display_name":"Search","slug":"search"},{"id":43,"name":"self-hosted","display_name":"Self-hosted","slug":"self-hosted"},{"id":50,"name":"static-analysis","display_name":"Static analysis","slug":"static-analysis"},{"id":18,"name":"synthetic-data","display_name":"Synthetic data","slug":"synthetic-data"},{"id":19,"name":"text-to-speech","display_name":"Text to speech","slug":"text-to-speech"},{"id":53,"name":"ui-components","display_name":"UI components","slug":"ui-components"},{"id":15,"name":"vector-database","display_name":"Vector database","slug":"vector-database"},{"id":21,"name":"video-editing","display_name":"Video editing","slug":"video-editing"},{"id":25,"name":"web-scraping","display_name":"Web scraping","slug":"web-scraping"},{"id":55,"name":"webassembly","display_name":"WebAssembly","slug":"webassembly"},{"id":23,"name":"workflow-automation","display_name":"Workflow automation","slug":"workflow-automation"}]" returns me the "expected json"