Article

Supercharged Development with Zed

development tooling minimalism zed-editor
AI-generated image in cartoon style of a programmer sitting in front of a desktop computer with a framed picture of the Zed editor logo on the opposite wall.
Posted on Monday, July the 28th 2025
25 min read
It probably goes without saying that successful development projects need first class tooling. The centerpiece of which is, of course, an excellent code editor. What makes an editor stand out for any one person is, obviously, extremely subjective. But there is at least one uncontroversial aspect in that editors should improve our ability to efficiently produce high quality code. I personally prefer comparatively minimalist editors for a couple of reasons: they are usually more performant, less distractive, and force me to engage deeply with the tech stack I'm using. Minimalism, however, is not the be all and end all. There are many complex features that, in my opinion, shouldn't be missing from a modern editor, because they reliably improve coding efficiency such as fuzzy finders, IntelliSense, or, arguably, AI integration. One of the editors that I found to do a remarkably good job at squaring this circle and delivering a performant and minimalist editor with just the right amount of modern productivity features is Zed, the new editor by the makers of Atom. Continue reading to find out more about Zed in this—admittedly opinionated and somewhat fanboyish—introduction to Zed.

Tl;dr (if you’re in a hurry)

Minimalist text editors should, in my opinion, usually be preferred over more comprehensive solutions like integrated development environments (IDEs) because of their positive effects on productivity and skill development. Terminal-based text editors, like Vim, however, are usually too complicated for teams with mixed levels of experience (or anyone without generous amounts of spare time, for that matter). Graphical text editor apps like Sublime Text, Atom, or Visual Studio Code are a solid middle ground. Zed is a new, modern text editor app that is both performant and has a minimalistic appeal while also delivering a modern feature set. The integrated remote development and agentic editing features, for example, are incorporated seamlessly and are a lot of fun to work with. Zed also has very smooth rendering, is configurable via JSON file, and is pretty intuitive for people coming from Visual Studio Code. Naturally, it also has some drawbacks. Zed is currently only available on macOS and Linux, and it may change pretty rapidly in the future due to very active development. Moreover, it’s not very clear if it’s free to use in business settings.

The case for minimal text editors

Many developers—even entire development teams—seem to use their integrated development environment (IDE) for nearly any task, even simple tasks like running a command in a command line tool or editing a system file.
Don’t get me wrong—I understand why: I have worked a lot with IDEs, primarily IntelliJ, and I know how amazing they can be. Especially when they simplify and speed up routine workflows or by enabling us to handle tasks we don’t have the necessary experience with or lack training in.

As much as they give an early boost, however, relying on IDEs also implies mental offloading which may become problematic in the long run. Delegating complex workflows to any sort of comprehensive tooling like an IDE, may result in a lack of in-depth understanding of the development process and technology stack. Unfortunately, this understanding is often critical to ensure projects run smoothly even when we, inevitably, hit rough patches. Additionally, if we do any kind of modern, large scale development and want to implement DevOps techniques we need to understand our development workflows before being able to automate them (e.g., in CI/CD pipelines).

One surefire way to do force ourselves to develop this knowledge and the associated skill set is to always start with minimal tooling. Surely, if we are able to work efficiently with a minimal, terminal-based text editor like (Neo)Vim, the shell, some command line tools, and automation scripts (and some extra time on our hands), we will have a much better understanding of a project’s nuts and bolts.

There is, moreover, a good chance that using a minimalist editor will free us from the typical performance tax of using an IDE, and there is a lower chance that we are distracted by visual clutter or disruptive housekeeping tasks (looking at you IntelliJ indexing). In other words, minimal editors are usually better for deeply focused work.

For mere mortals, VS Code > Vim

The most basic variant of a setup as outlined above with a simple and fast text editor, the shell, some command line tools, and automation scripts would naturally incorporate a classical, terminal-based editor like (Neo)Vim.

I’m not a (Neo)Vim expert, but I totally understand why so many people still use it in spite of all the other options. It’s simple, fast, keyboard-focused, and distraction-free. That being said, I also heavily dislike the amount of work you have to invest into keeping your (Neo)Vim setup working by altering your configuration as well as keeping plugins up-to-date and interoperable. (Some (Neo)Vim die-hards can probably earn an advanced degree with the amount of time they invest into editor configuration, maintenance, and maybe even plugin development. )

I’m using (Neo)Vim as a proxy for most minimal editors, by the way. There are quite a few other options: GNU Emacs, Nano, Micro, Helix, and lots more (see here for nice write up). But all of them, at least partially, have the same problems, in my opinion.

Yes, there are some distributions (like AstroNvim) that let us minimize this effort, but you still have to get into (Neo)Vim configuration if you want to tweak something to fit your needs. Not to mention that you have to learn at least one configuration language and will likely have to choose from one of multiple package managers. And even if you got everything working, there is the learning curve to contend with. If you don’t build Vim motion muscle memory in countless editor sessions, you will most likely not be able to use it effectively. In fact, it may actually slow you down.

Meme about first time Vim users.
Source: https://tinyurl.com/4hvh7m87

Thankfully, there is a middle ground between IDEs and super minimalist, terminal-based editors like (Neo)Vim in the form of graphical text editor applications like Visual Studio Code (VS Code), Sublime Text, or Atom. My first introduction to these kinds of editors was Sublime Text almost ten years back (although it exists much longer than that — since 2008). I immediately loved the unobtrusive, minimal layout and the option to trigger editor commands using the command palette rather than having to point and click on menus. It’s also extendable and very fast.

Sublime Text window for a simple NestJS project showing main editor pane, project browser, status bar, and command palette.
Sublime Text window for a simple NestJS project showing main editor pane, project browser, status bar, and command palette.

Visual Studio Code (VS Code)—which has been default text editor app for a long time now—is a perfect example of how attractive the combination of minimalism and extensibility may be. VS Code shares much of Sublime Text’s strong points while also having the added upside that it’s free and open source. VS Code also adds some more sensible out of the box capabilities like an integrated terminal and a graphical debugging panel.

Zed enters the fray

While I generally like VS Code—it surely is one of the best Microsoft products ever—I also feel that it has some shortcomings. Among other things, it’s based on the Electron framework which, conveniently, uses web technologies to create desktop apps but has the drawback that it is neither the fastest nor the most resource friendly technology option. Additionally, I think VS Code’s default feature set is somewhat stuck in the past. One example of this is the lack of an integrated remote mode.

Zed editor slogan: code at the speed of thought

Zed is a powerful and modern text editor built in Rust that—at least according to its developers—lets us code at the speed of thought. (Clearly not my speed of thought. Zed is actually pretty fast. ). Some reviewers have called Zed a VS Code killer due to its combination of cutting edge performance and a modern out of the box feature set. Even if this is a bit too hyperbolic, I can assure you that there are quite a few reasons why Zed may become a strong rival.

Zed, for instance, natively integrates a lot of features that I would consider standard (or at least nice to have) for most development teams that want to leverage cutting edge dev techniques into a well-rounded package. It gives us instant access to

That’s quite a lot. Plus, if you’re unhappy with Zed’s—already outstanding—out of the box capabilities, there’s a plug-in ecosystem to pick extensions from. Or, you can take a look at the roadmap to see if something down the line will change your mind (like support for notebook-style editing).

Even though Zed with this amount of features, is on the brink of wandering into IDE/swiss army knife territory, it somehow manages to retain the performance, look, and feel of a minimal text editor like Sublime Text.

Zed is, by the way, also open source, free (for personal use), and under active development (nearly 62k stars on GitHub, over 1k contributors, and weekly releases).

Two things I was really curious about when I first learned about Zed were the integrated remote development mode and the support for agentic editing. These features are in my opinion, a must-have for any truly modern development project.

Remote development: means splitting your development setup into a frontend running locally and a backend part that runs in another context (for example on a remote machine, local or remote container or virtual machine). Remote development enables us to use isolated development environments that don’t affect the host machine and usually also are easier to set up, update, and restore. (Like dev containers on Kubernetes.) It, moreover, allows us to run computationally heavy processes on, potentially more beefy, remote machines. For teams struggling with maintaining and documenting local dev setups—especially for multiple platforms—or running workloads with heavy resource requirements, remote development should definitely be considered as one of the go-to solutions.

Agentic editing: Discussions about whether artificial intelligence (AI) will destroy humanity or not set aside, I’m still convinced that using AI code assistants to directly modify your code base is one of the core techniques in software development in the short and medium-term future. It is, at the very least, code completion on steroids. And, agentic editing—enabling AI agents to make changes to the code base—may raise productivity and boost the quality of produced code for simple tasks. (I’m torn about whether it will boost tasks with higher complexity, but that’s another story.) Another really interesting aspect of agentic editing is that it allows text editors to be enhanced with a lot of features that are quite commonly provided by IDEs, like refactoring tools, without explicit programming. In other words, if you manage to find the right prompt, you can potentially replace most common IDE features by simply instructing the AI agent to handle them.

Zed makes it pretty easy to get started with both development techniques by making them available out of the box and integrating them neatly into the editor. Obviously, there is a small initial learning curve attached to working with both remote mode and AI agents. But the look and feel is great and makes both techniques very accessible.

Some other notable features

Besides the remote development and agentic editing features, there are also some minor features that caught my attention.

Graphical fidelity: Zed is very appealing from a visual perspective. For instance, the font rendering is beautiful and scrolling is very smooth. (Powered by its dedicated GPU-accelerated UI framework GPUI.)

Configuration: Just like in VS Code, there is a settings JSON file that we may check into version control to track changes or distribute it in our team. Some configuration options that would be serialized in the configuration JSON file are also, conveniently, available from the command palette. For example, we may choose themes using the theme selector: toggle command. (To use a community theme, just download the JSON file and put it into ~/.config/zed/themes then select it using the command palette.) The customize key binding editor is available with zed: open keymap.

Intuitiveness: Speaking of key bindings, the default key map will seem familiar coming from VS Code. For example, the command palette is available via CMD + SHIFT + p and the fuzzy finder is opened with CMD + p. Vim motion will also, obviously, carry over to Zed’s Vim mode. Standard UI features, like split panes and tabs are available and seem to work just as we expect them to.

Limitations

Zed is only available on macOS and Linux for now. Since development is very active, things may also change very quickly. Don’t expect stable features quite yet.

Obviously, since the editor has not been available for very long, its ecosystem is not as expansive as, for example, that of VS Code.

Another important thing is that with the free plan, edit predictions and prompts are limited. It is also not entirely clear to me how, or to what extent, Zed is free to use in a business setting.

Demo time

Let’s create a small NestJS app to illustrate how Zed may supercharge your dev projects.

npx @nestjs/cli new --package-manager npm --strict theproject

Full log to be found here

Commit the initial changes.

git add .
git commit -m 'Initial commit'

Confirm that our NestJS server is up and running.

$ curl localhost:3000
Hello World!%  

A Zed installation comes with a useful command line interface (CLI) utility zed. We may use it to open our project directly from the command line.

zed theproject

As we can see, there is basically nothing to get excited about at first—only Sublime Text-like minimalism.

Zed editor window for a simple NestJS project.
Zed editor window for a simple NestJS project.

To hit the ground running, let’s now use agentic editing to make a few changes to our app.

The demo requires access to an LLM provider. I’m using GitHub Copilot Free (Claude Sonnet 3.5 model) which is accessible for free with your GitHub account and directly available in Zed if you login with GitHub.

We start a thread for interacting with the LLM coding assistant via the agent: new thread editor action (accessible via the command palette CMD + SHIFT + p on macOS). This opens the agent panel to the side for interacting with the configured AI assistant. Additionally, we need to make sure that the profile Write is selected in the footer menu of the agent panel so that our agent may change the files in the project.

The Zed agent panel processing a prompt.
The Zed agent panel processing a prompt.

To demonstrate Zed’s remote development feature, we let the agent set up a dev container configuration for us. The remote development feature simply connects to the remote end using SSH. A tried and true solution. That being said, it requires our container to run a properly configured OpenSSH server. For simplicity’s sake, we ask the AI agent to pull the configuration from one of my public template repositories. We also ask the agent to change the SSH port from 2022 to 2122 and to rename the image and container.

Prompts to set up remote development

  • Download the master of the remote repository at https://github.com/fkurz/zed-devcontainer.git to the current directory as a ZIP file.

  • Extract the .devcontainer directory of the ZIP file to the root of this project.

  • Yes, please clean up the ZIP file.

  • Please make the following changes to the configuration in the .devcontainer directory:

    • the devcontainer should be accessible via SSH on port 2122 instead of 2022
    • the name of the image should be fk.me/zed instead of friedrichkurz.me/zeddevcon
    • the name of the container should be zed

Full interaction in the appendix

We could probably now also ask the agent to build the image for us. Let’s, however, do this ourselves this time to expedite things. Sometimes, simply typing the command is faster than typing an agent prompt.

docker build -t fk.me/zed -f .devcontainer/Dockerfile .

And then let’s run the dev container using devcontainer CLI

devcontainer up --workspace-folder=.

Let’s also add the following SSH configuration to ~/.ssh/config in order to set default options UserKnownHostsFile=/dev/null and StrictHostKeyChecking=no so that we may bypass host checks.

# ~/.ssh/config

Host zed
  HostName localhost
  Port 2122
  User zed
  StrictHostKeyChecking no
  UserKnownHostsFile /dev/null

Again using the zed CLI command, we may now simply open a connection to the devcontainer via SSH by passing a connection URL:

zed ssh://zed:zed@zed:2122/workspace
Zed window in remote development mode.
Zed window in remote development mode.

We should now have our local repository open in a new Zed window. The URL zed@zed:2122 indicates that we are in remote development mode. (In this case we only have a pseudo remote connection to a Docker container, but it would work similarly for an actual remote connection scenario.)

Notes on remote development mode

With a local dev container up and running, remote development mode is very fast. I didn’t notice any input lag. I was only occasionally reminded that I’m not working on my host machine—when I picked the wrong terminal, when Git asked me to configure user and email, or when some tools had to be installed that are typically present. But that’s it, really. Zed, very conveniently, also lets us authenticate to the remote, open a new remote editor window, and change to our workspace in one go via the zed command by passing credentials and directory path in the URL.

Now, let’s spice things up a bit by adding Fastify and the Handlebars template engine.

Prompts to refactor the NestJS app to use Fastify and Handlebars

  1. Update the configuration in src/main.ts so that our server uses Fastify.
  2. Update the configuration to use NestJS’s built-in useStaticAssets method instead of registering Fastify’s static plugin directly.
  3. Configure the application to use Handlebars as template engine. Use the setViewEngine method. Install the handlebars package and save it to package.json.
  4. Update src/app.controller.ts to render the index.hbs template.
Agent updating a NestJS application to use Fastify.
Agent updating a NestJS application to use Fastify.

Note from the screenshot above that not only does the agent provide us with a list of proposed changes in the agent panel, but Zed will also highlight the diff to the previous iteration in the editor tab and mark changed files in the project browser. This is very helpful when we want to verify that changes made by the agent are in line with our expectations.

Now, let’s start the dev server.

pnpm run start:dev

Opening localhost:3000 we should see something like this.

NestJS + Handlebars hello world app.
NestJS + Handlebars hello world app.

Notes on agentic editing

Agentic editing is seamlessly integrated into Zed and was fun to work with. The automatic Git diff highlighting works well in letting us control changes by the agent. Moreover, agents also neatly prompt us to confirm tool usage (like downloading via curl or npm install). However, agent behavior is, also frequently disappointing on more complex tasks and requires more detailed instructions reducing their effectiveness. For example, neither Sonnet 3.5 nor GPT-4.1 created a working dev container configuration from scratch. For some IDE features, like refactoring tools, agentic editing is a fairly solid replacement that doesn’t require downloading an extension and does not incur a performance penalty on the editor.

Summary

Text editors like Visual Studio Code or Sublime Text are powerful tools for development. They should, in my opinion, often be preferred to IDEs because of their positive effects on concentration and knowledge acquisition.

Zed is a new and modern text editor. While still being minimal and performant, it also offers a set of out-of-the-box capabilities that are essential for modern development or may become so in the near future. The integration of agentic editing in a minimal, performant text editor is particularly intriguing, since agents may substitute a lot of features that are usually only included in IDEs (like refactoring tools), without the performance penalty.

Keep in mind that Zed, being a relatively new editor, has a few limitations: it is, for example, not available on all platforms, has a limited ecosystem, and may be changing rapidly over the next months and years.

Bottom line: Zed is definitely worth checking out if you are looking for a performant and modern replacement for graphical text editors like VS Code. Follow the link below to get started working with Zed!

Appendix

Full NestJS new project log

Click to expand…
  We will scaffold your app in a few seconds..

CREATE .prettierrc (51 bytes)
CREATE README.md (5028 bytes)
CREATE eslint.config.mjs (836 bytes)
CREATE nest-cli.json (171 bytes)
CREATE package.json (2036 bytes)
CREATE tsconfig.build.json (97 bytes)
CREATE tsconfig.json (541 bytes)
CREATE src/app.controller.ts (274 bytes)
CREATE src/app.module.ts (249 bytes)
CREATE src/app.service.ts (142 bytes)
CREATE src/main.ts (228 bytes)
CREATE test/jest-e2e.json (183 bytes)
CREATE src/app.controller.spec.ts (617 bytes)
CREATE test/app.e2e-spec.ts (674 bytes)

 Installation in progress...

🚀  Successfully created a new project
👉  Get started with the following commands:

$ cd .
$ npm run start


                          Thanks for installing Nest 🙏
                 Please consider donating to our open collective
                        to help us maintain this package.


               🍷  Donate: https://opencollective.com/nest

Full agent interaction to create dev container

Click to expand…
# Download GitHub Repository as ZIP

## User

Download the master of the remote repository at https://github.com/fkurz/zed-devcontainer.git to the current directory as a ZIP file.

## Agent

I'll help you download the ZIP file of the master branch from the specified GitHub repository. We can use the `terminal` command to accomplish this with `curl`. GitHub provides a direct link to download repository archives in ZIP format.

**Use Tool: terminal (tooluse_yt7fFtp8Rvq48Sw2kcquxQ)**
```json
{
  "cd": "theproject",
  "command": "curl -L https://github.com/fkurz/zed-devcontainer/archive/refs/heads/master.zip -o zed-devcontainer-master.zip"
}
```

**Tool Results: tooluse_yt7fFtp8Rvq48Sw2kcquxQ**

```
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100  8155    0  8155    0     0  15298      0 --:--:-- --:--:-- --:--:-- 15298
```
## Agent

The ZIP file has been successfully downloaded as `zed-devcontainer-master.zip` in the project directory. The file is approximately 8 KB in size. You can now extract this ZIP file if needed. Would you like me to help you extract the contents?

## User

Extract the `.devcontainer` directory of the ZIP file to the root of this project.

## Agent

I'll help you extract just the `.devcontainer` directory from the ZIP file. We'll use the `unzip` command with specific path targeting.

**Use Tool: terminal (tooluse_RFjPTjrsSWCleuUNYfeCTA)**
```json
{
  "cd": "theproject",
  "command": "unzip -j zed-devcontainer-master.zip \"zed-devcontainer-master/.devcontainer/*\" -d .devcontainer"
}
```

**Tool Results: tooluse_RFjPTjrsSWCleuUNYfeCTA**

Command "unzip -j zed-devcontainer-master.zip "zed-devcontainer-master/.devcontainer/*" -d .devcontainer" failed with exit code 1.

```
Archive:  zed-devcontainer-master.zip
ff5206cf675b3a017f8de7aba302bf092053a176
caution: filename not matched:  zed-devcontainer-master/.devcontainer/*
```
## Agent

I apologize for the error in my first attempt. Let me verify the contents of the ZIP file first to ensure we're using the correct paths.

**Use Tool: terminal (tooluse_4-WpAN0XRs6EooXyTNrt_g)**
```json
{
  "cd": "theproject",
  "command": "unzip -l zed-devcontainer-master.zip"
}
```

**Tool Results: tooluse_4-WpAN0XRs6EooXyTNrt_g**

```
Archive:  zed-devcontainer-master.zip
ff5206cf675b3a017f8de7aba302bf092053a176
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  06-06-2025 06:39   zed-devcontainer-main/
        0  06-06-2025 06:39   zed-devcontainer-main/.devcontainer/
     1198  06-06-2025 06:39   zed-devcontainer-main/.devcontainer/Dockerfile
      339  06-06-2025 06:39   zed-devcontainer-main/.devcontainer/devcontainer.json
     1203  06-06-2025 06:39   zed-devcontainer-main/.devcontainer/sshd_config.template
    11357  06-06-2025 06:39   zed-devcontainer-main/LICENSE
     3392  06-06-2025 06:39   zed-devcontainer-main/README.md
---------                     -------
    17489                     7 files
```
## Agent

Now I can see that the files are actually in a directory called `zed-devcontainer-main` (not `master`). Let me extract the `.devcontainer` directory with the correct path:

**Use Tool: terminal (tooluse_xvQxm6ZwR6OUGvUEehw3wQ)**
```json
{
  "cd": "theproject",
  "command": "unzip -j zed-devcontainer-master.zip \"zed-devcontainer-main/.devcontainer/*\" -d .devcontainer"
}
```

**Tool Results: tooluse_xvQxm6ZwR6OUGvUEehw3wQ**

```
Archive:  zed-devcontainer-master.zip
ff5206cf675b3a017f8de7aba302bf092053a176
  inflating: .devcontainer/Dockerfile
  inflating: .devcontainer/devcontainer.json
  inflating: .devcontainer/sshd_config.template
```
## Agent

Great! I've successfully extracted the `.devcontainer` directory and its contents to your project root. The extracted files are:
1. `.devcontainer/Dockerfile`
2. `.devcontainer/devcontainer.json`
3. `.devcontainer/sshd_config.template`

Would you like me to clean up by removing the downloaded ZIP file?

## User

Yes, please clean up the ZIP file.

## Agent

I'll remove the ZIP file using the `terminal` command.

**Use Tool: terminal (tooluse_apXkSI7nSDuuaxiF8T2Xmg)**
```json
{
  "cd": "theproject",
  "command": "rm zed-devcontainer-master.zip"
}
```

**Tool Results: tooluse_apXkSI7nSDuuaxiF8T2Xmg**

Command executed successfully.
## Agent

The ZIP file has been removed. You now have just the extracted `.devcontainer` directory and its contents in your project root, without any of the temporary download files.

## User

Plase make the following changes to the configuration in the .devcontainer directory:

* the devcontainer should be accessible via SSH on port 2122 instead of 2022
* the name of the image should be fk.me/zed instead of friedrichkurz.me/zeddevcon
* the name of the container should be zed

## Agent

I'll help you modify the `.devcontainer` configuration files with these changes. Let me first check the current content of the relevant files.

**Use Tool: read_file (tooluse_hI6XHduJSKmp9wWBCpZu2g)**
```json
{
  "path": "theproject/.devcontainer/devcontainer.json"
}
```

**Tool Results: tooluse_hI6XHduJSKmp9wWBCpZu2g**

{
    "name": "zeddevcon",
    "image": "friedrichkurz.me/zeddevcon",
    "overrideCommand": false,
    "runArgs": ["--network=host", "--name=zeddevcon"],
    "forwardPorts": [2022],
    "mounts": [
        {
            "source": "${localWorkspaceFolder}",
            "target": "/workspace",
            "type": "bind"
        }
    ]
}

## Agent

Let me make the necessary changes to the `devcontainer.json` file:

**Use Tool: edit_file (tooluse_SAG5GN8pRnqkTF54OvuyQw)**
```json
{
  "display_description": "Update container name, image name, and SSH port in devcontainer.json",
  "path": "theproject/.devcontainer/devcontainer.json",
  "mode": "overwrite"
}
```

**Tool Results: tooluse_SAG5GN8pRnqkTF54OvuyQw**

Edited theproject/.devcontainer/devcontainer.json:

```diff
@@ -1,14 +1,14 @@
 {
-    "name": "zeddevcon",
-    "image": "friedrichkurz.me/zeddevcon",
-    "overrideCommand": false,
-    "runArgs": ["--network=host", "--name=zeddevcon"],
-    "forwardPorts": [2022],
-    "mounts": [
-        {
-            "source": "${localWorkspaceFolder}",
-            "target": "/workspace",
-            "type": "bind"
-        }
-    ]
+  "name": "zed",
+  "image": "fk.me/zed",
+  "overrideCommand": false,
+  "runArgs": ["--network=host", "--name=zed"],
+  "forwardPorts": [2122],
+  "mounts": [
+    {
+      "source": "${localWorkspaceFolder}",
+      "target": "/workspace",
+      "type": "bind"
+    }
+  ]
 }

```


Debug Output:

```json
{
  "original_path": ".devcontainer/devcontainer.json",
  "new_text": "{\n  \"name\": \"zed\",\n  \"image\": \"fk.me/zed\",\n  \"overrideCommand\": false,\n  \"runArgs\": [\"--network=host\", \"--name=zed\"],\n  \"forwardPorts\": [2122],\n  \"mounts\": [\n    {\n      \"source\": \"${localWorkspaceFolder}\",\n      \"target\": \"/workspace\",\n      \"type\": \"bind\"\n    }\n  ]\n}\n",
  "old_text": "{\n    \"name\": \"zeddevcon\",\n    \"image\": \"friedrichkurz.me/zeddevcon\",\n    \"overrideCommand\": false,\n    \"runArgs\": [\"--network=host\", \"--name=zeddevcon\"],\n    \"forwardPorts\": [2022],\n    \"mounts\": [\n        {\n            \"source\": \"${localWorkspaceFolder}\",\n            \"target\": \"/workspace\",\n            \"type\": \"bind\"\n        }\n    ]\n}\n",
  "raw_output": {
    "raw_edits": "```\n{\n    \"name\": \"zed\",\n    \"image\": \"fk.me/zed\",\n    \"overrideCommand\": false,\n    \"runArgs\": [\"--network=host\", \"--name=zed\"],\n    \"forwardPorts\": [2122],\n    \"mounts\": [\n        {\n            \"source\": \"${localWorkspaceFolder}\",\n            \"target\": \"/workspace\",\n            \"type\": \"bind\"\n        }\n    ]\n}\n```",
    "parser_metrics": {
      "tags": 0,
      "mismatched_tags": 0
    }
  }
}
```

## Agent

Now let me check the `sshd_config.template` to ensure we update the SSH port there as well:

**Use Tool: read_file (tooluse_5kG4M4wASfa2RuEDfl0WRA)**
```json
{
  "path": "theproject/.devcontainer/sshd_config.template"
}
```

**Tool Results: tooluse_5kG4M4wASfa2RuEDfl0WRA**

# This sshd was compiled with PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Port ${THE_SSH_PORT}

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
KbdInteractiveAuthentication no

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the KbdInteractiveAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via KbdInteractiveAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and KbdInteractiveAuthentication to 'no'.
UsePAM yes

X11Forwarding yes
PrintMotd no

# Allow client to pass locale environment variables
AcceptEnv LANG LC_*

AllowUsers ${THE_USER_NAME}

## Agent

Now let me check the Dockerfile to see if we need to make any changes there:

**Use Tool: read_file (tooluse_imncDBudRCuXt1Ljq8j6sA)**
```json
{
  "path": "theproject/.devcontainer/Dockerfile"
}
```

**Tool Results: tooluse_imncDBudRCuXt1Ljq8j6sA**

FROM ubuntu:24.04

LABEL docker.io/image=friedrichkurz.me/zed-devcontainer

ARG THE_USER_NAME
ARG THE_USER_PASSWORD
ARG THE_USER_UID
ARG THE_SSH_PORT
ARG THE_GIT_VERSION="1:2.43.0-1ubuntu7.2"

COPY "./.devcontainer/sshd_config.template" "/tmp/sshd_config.template"

SHELL ["/usr/bin/bash", "-c"]

RUN <<EOF
set -euo pipefail
apt-get update
# Add SSH user with password for SSH authentication with root privileges
useradd -m -d "/home/${THE_USER_NAME}" -s /bin/bash -g sudo -G sudo -u "${THE_USER_UID}" "${THE_USER_NAME}"
printf "${THE_USER_NAME}:${THE_USER_PASSWORD}" | chpasswd
# Install OpenSSH server
# See https://github.com/fkurz/devcontainer-ssh/blob/main/.devcontainer/base/Dockerfile
apt-get update
apt-get install --yes gettext-base openssh-server sudo
mkdir -p /etc/ssh
mkdir -p /var/run/sshd
mkdir -p /etc/ssh/sshd_config.d
cat /tmp/sshd_config.template \
  | envsubst '$THE_SSH_PORT $THE_USER_NAME $THE_USER_PASSWORD' \
  | tee /etc/ssh/sshd_config.d/devcontainer.conf
apt-get remove --yes gettext-base
rm /tmp/sshd_config.template
command -v sshd
# Install Git
apt-get install --yes git="$THE_GIT_VERSION"
git --version
EOF

ENTRYPOINT ["/usr/sbin/sshd", "-D"]

EXPOSE ${THE_SSH_PORT}

## Agent

I see that the Dockerfile also needs to be updated with the new image name. I'll make this change:

**Use Tool: edit_file (tooluse_eMCHjId2Qs-a_sEiaU4_Ag)**
```json
{
  "mode": "overwrite",
  "path": "theproject/.devcontainer/Dockerfile",
  "display_description": "Update image name in Dockerfile"
}
```

**Tool Results: tooluse_eMCHjId2Qs-a_sEiaU4_Ag**

Edited theproject/.devcontainer/Dockerfile:

```diff
@@ -1,6 +1,6 @@
 FROM ubuntu:24.04
 
-LABEL docker.io/image=friedrichkurz.me/zed-devcontainer
+LABEL docker.io/image=fk.me/zed
 
 ARG THE_USER_NAME
 ARG THE_USER_PASSWORD

```


Debug Output:

```json
{
  "original_path": ".devcontainer/Dockerfile",
  "new_text": "FROM ubuntu:24.04\n\nLABEL docker.io/image=fk.me/zed\n\nARG THE_USER_NAME\nARG THE_USER_PASSWORD\nARG THE_USER_UID\nARG THE_SSH_PORT\nARG THE_GIT_VERSION=\"1:2.43.0-1ubuntu7.2\"\n\nCOPY \"./.devcontainer/sshd_config.template\" \"/tmp/sshd_config.template\"\n\nSHELL [\"/usr/bin/bash\", \"-c\"]\n\nRUN <<EOF\nset -euo pipefail\napt-get update\n# Add SSH user with password for SSH authentication with root privileges\nuseradd -m -d \"/home/${THE_USER_NAME}\" -s /bin/bash -g sudo -G sudo -u \"${THE_USER_UID}\" \"${THE_USER_NAME}\"\nprintf \"${THE_USER_NAME}:${THE_USER_PASSWORD}\" | chpasswd\n# Install OpenSSH server\n# See https://github.com/fkurz/devcontainer-ssh/blob/main/.devcontainer/base/Dockerfile\napt-get update\napt-get install --yes gettext-base openssh-server sudo\nmkdir -p /etc/ssh\nmkdir -p /var/run/sshd\nmkdir -p /etc/ssh/sshd_config.d\ncat /tmp/sshd_config.template \\\n  | envsubst '$THE_SSH_PORT $THE_USER_NAME $THE_USER_PASSWORD' \\\n  | tee /etc/ssh/sshd_config.d/devcontainer.conf\napt-get remove --yes gettext-base\nrm /tmp/sshd_config.template\ncommand -v sshd\n# Install Git\napt-get install --yes git=\"$THE_GIT_VERSION\"\ngit --version\nEOF\n\nENTRYPOINT [\"/usr/sbin/sshd\", \"-D\"]\n\nEXPOSE ${THE_SSH_PORT}\n",
  "old_text": "FROM ubuntu:24.04\n\nLABEL docker.io/image=friedrichkurz.me/zed-devcontainer\n\nARG THE_USER_NAME\nARG THE_USER_PASSWORD\nARG THE_USER_UID\nARG THE_SSH_PORT\nARG THE_GIT_VERSION=\"1:2.43.0-1ubuntu7.2\"\n\nCOPY \"./.devcontainer/sshd_config.template\" \"/tmp/sshd_config.template\"\n\nSHELL [\"/usr/bin/bash\", \"-c\"]\n\nRUN <<EOF\nset -euo pipefail\napt-get update\n# Add SSH user with password for SSH authentication with root privileges\nuseradd -m -d \"/home/${THE_USER_NAME}\" -s /bin/bash -g sudo -G sudo -u \"${THE_USER_UID}\" \"${THE_USER_NAME}\"\nprintf \"${THE_USER_NAME}:${THE_USER_PASSWORD}\" | chpasswd\n# Install OpenSSH server\n# See https://github.com/fkurz/devcontainer-ssh/blob/main/.devcontainer/base/Dockerfile\napt-get update\napt-get install --yes gettext-base openssh-server sudo\nmkdir -p /etc/ssh\nmkdir -p /var/run/sshd\nmkdir -p /etc/ssh/sshd_config.d\ncat /tmp/sshd_config.template \\\n  | envsubst '$THE_SSH_PORT $THE_USER_NAME $THE_USER_PASSWORD' \\\n  | tee /etc/ssh/sshd_config.d/devcontainer.conf\napt-get remove --yes gettext-base\nrm /tmp/sshd_config.template\ncommand -v sshd\n# Install Git\napt-get install --yes git=\"$THE_GIT_VERSION\"\ngit --version\nEOF\n\nENTRYPOINT [\"/usr/sbin/sshd\", \"-D\"]\n\nEXPOSE ${THE_SSH_PORT}\n",
  "raw_output": {
    "raw_edits": "```\nFROM ubuntu:24.04\n\nLABEL docker.io/image=fk.me/zed\n\nARG THE_USER_NAME\nARG THE_USER_PASSWORD\nARG THE_USER_UID\nARG THE_SSH_PORT\nARG THE_GIT_VERSION=\"1:2.43.0-1ubuntu7.2\"\n\nCOPY \"./.devcontainer/sshd_config.template\" \"/tmp/sshd_config.template\"\n\nSHELL [\"/usr/bin/bash\", \"-c\"]\n\nRUN <<EOF\nset -euo pipefail\napt-get update\n# Add SSH user with password for SSH authentication with root privileges\nuseradd -m -d \"/home/${THE_USER_NAME}\" -s /bin/bash -g sudo -G sudo -u \"${THE_USER_UID}\" \"${THE_USER_NAME}\"\nprintf \"${THE_USER_NAME}:${THE_USER_PASSWORD}\" | chpasswd\n# Install OpenSSH server\n# See https://github.com/fkurz/devcontainer-ssh/blob/main/.devcontainer/base/Dockerfile\napt-get update\napt-get install --yes gettext-base openssh-server sudo\nmkdir -p /etc/ssh\nmkdir -p /var/run/sshd\nmkdir -p /etc/ssh/sshd_config.d\ncat /tmp/sshd_config.template \\\n  | envsubst '$THE_SSH_PORT $THE_USER_NAME $THE_USER_PASSWORD' \\\n  | tee /etc/ssh/sshd_config.d/devcontainer.conf\napt-get remove --yes gettext-base\nrm /tmp/sshd_config.template\ncommand -v sshd\n# Install Git\napt-get install --yes git=\"$THE_GIT_VERSION\"\ngit --version\nEOF\n\nENTRYPOINT [\"/usr/sbin/sshd\", \"-D\"]\n\nEXPOSE ${THE_SSH_PORT}\n```",
    "parser_metrics": {
      "tags": 0,
      "mismatched_tags": 0
    }
  }
}
```

## Agent

I've made all the requested changes:

1. Changed the SSH port from 2022 to 2122 in `devcontainer.json`
2. Updated the image name from `friedrichkurz.me/zeddevcon` to `fk.me/zed` in both `devcontainer.json` and `Dockerfile`
3. Changed the container name from `zeddevcon` to `zed` in `devcontainer.json`

The SSH port in the `sshd_config.template` is already parameterized using the `${THE_SSH_PORT}` variable, so it will automatically use whatever port is specified when the container is built.

All the changes have been made successfully. Would you like me to verify anything specific in these changes?
friedrichkurz.me

© 2025 Friedrich Kurz

Privacy Policy