Skip to content

Zed editor experiment

William B edited this page May 8, 2026 · 4 revisions

Migrating to Zed

Zed is dopest new editor from the devs that brought us the Atom editor back in the day. It's written entirely from the ground up using Rust and is snappy as hell.

Pros:

  • Rust, so it's bloody fast and doesn't eat your RAM (looking at you electron)
  • Supports Python OOTB with Ruff, basedpywrite, and poetry support with options to use other language servers (except for pylance because closed source M$)
  • Supports custom agents, MCP servers, and basically every LLM provider out there.
  • Copilot integration works
  • Parallel agents
  • Migrating settings from vscode seems relatively straightforward

Cons:

  • Devcontainer support is still in it's infancy. It works but it's clunky and missing built in features like Rebuild & reopen in dev container (this is manual, stop container elsewhere -> open project again in dev container minor but annoying)
  • No Pylance, arguably the best Python language server at the moment but open source alternatives such as ty from the makers of Ruff are making great progress.

Setting up API

Zed <-> Colima

  1. Ensure the latest docker compose is installed
brew install docker-compose
  1. Point the DOCKER_HOST to your Colima instance in ~/.zshrc
➜ colima status
...
INFO[0000] socket: unix:///Users/wbanks/.colima/default/docker.sock


export DOCKER_HOST="unix:///Users/wbanks/.colima/default/docker.sock"

Updating the devcontainer configs for Zed

devcontainer.json

We haven't updated our devcontainer.json for quite some time and it uses some legacy vscode shorthand that Zed cannot parse.

Update the "features": section with fully quantified names:

"features": {
    "ghcr.io/devcontainers/features/docker-from-docker:1": {
        "moby": true
    },
    "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {
        "helm": "latest",
        "minikube": "none"
    },
    "ghcr.io/devcontainers/features/node:1": {}
},

Additionally, Zed's port exposure is limited to use of appPort for port forwarding. Support for forwardPorts attributes is in the development pipeline

Near the top of devcontainer.json as a root element add "appPort": [6011],:

"workspaceFolder": "/workspace",
"shutdownAction": "stopCompose",
"appPort": [6011], <---
"remoteEnv": {
    "PATH": "/home/vscode/.local/bin:${containerEnv:PATH}" // give our installed Python modules precedence
},

docker-compose.yml

Update the services -> notify-api node, and add:

ports:
    - "6011:6011"

Running the dev container

Before opening the container in Zed, find, stop, then remove the notification-api_devcontainer-notify-api-1 container ONLY. Leave redis and db containers.

  1. Open Zed and open (⌘ + O) the notifications-api folder .
  2. Once opened you should receive a notification on the bottom right prompting you to open in dev container
    • If not, press ⌘ + shift + P -> type container -> select projects: open dev container

Unfortunately, Zed blocks all other actions in the editor while the container is building. It may take some time but it'll eventually spin up.

Configuring the run tasks

Zed uses .zed/tasks.json primarily for running applications, it's nearly identical to launch.json in nature.

  1. Create .zed/tasks.json at the root of the project
  2. Add the following tasks:
[
    {
        "label": "Python: Flask",
        "command": "poetry",
        "args": [
            "run",
            "python",
            "-m",
            "flask",
            "run",
            "--no-debugger",
            "-p",
            "6011",
            "--host=0.0.0.0"
        ],
        "env": {
            "FLASK_APP": "application.py",
            "FLASK_ENV": "development"
        },
        "reveal": "always"
    },
    {
        "label": "Python: Gunicorn",
        "command": "poetry",
        "args": [
            "run",
            "gunicorn",
            "--config",
            "gunicorn_config.py",
            "application"
        ],
        "env": {
            "FLASK_APP": "application.py",
            "FLASK_ENV": "development"
        },
        "reveal": "always"
    },
    {
        "label": "Python: Celery",
        "command": "poetry",
        "args": [
            "run",
            "celery",
            "--app",
            "run_celery",
            "worker",
            "--pidfile",
            "/tmp/celery.pid",
            "--concurrency=4",
            "-l",
            "DEBUG",
            "-Q",
            "database-tasks,-priority-database-tasks.fifo,-normal-database-tasks,-bulk-database-tasks,job-tasks,notify-internal-tasks,periodic-tasks,priority-tasks,normal-tasks,bulk-tasks,reporting-tasks,research-mode-tasks,retry-tasks,service-callbacks-retry,send-sms-tasks,send-sms-high,send-sms-medium,send-sms-low,send-throttled-sms-tasks,send-email-high,send-email-medium,send-email-low,send-email-tasks,service-callbacks,delivery-receipts"
        ],
        "reveal": "always"
    }
]

Now try running the task:

  1. Press F4 -> select Run in the modal that appears
  2. Select Python: Flask
  3. Note that the terminal appears and the app runs
  4. Make sure you can hit localhost:6011 in your browser

Clone this wiki locally