Skip to content
runrlyPublic

About

Create and open Zed .code-workspace files through folder mode or a marker-protected symlink dock.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Latest commit

 

History

62 Commits

Folders and files

Repository files navigation

Zed Workspace Dock

Zed Workspace Dock

CI Release License Rust 1.96+

Rust CLI (zwd) for opening multi-project Zed sessions from .code-workspace files.

Zed can open multiple folders directly, but its terminal still benefits from a single visible root in some workflows. Zed Workspace Dock can create a lock-protected cache directory where each project folder is linked, then open that dock root in Zed. Running ls in the terminal shows the linked projects without copying source code.

Install - Quick start - Usage - Workspace files - Development

Note

On Windows, symlink dock mode creates directory symbolic links. Windows may require Developer Mode, SeCreateSymbolicLinkPrivilege, or an administrator shell to create those links.

Features

  • Create registered Zed workspace files from one or more project folders.
  • Open, inspect, edit, or delete a workspace by registered name or by .code-workspace path.
  • Choose between direct folders mode and managed symlink dock mode.
  • Add or remove one or more project folders while synchronizing an existing dock safely.
  • Install global Zed tasks backed by the packaged task templates.
  • Reconcile dock links safely using .zwd-lock.json ownership locks, preserving extra files and manual symlinks.
  • Use the short zwd command for repeated terminal workflows.

Install

Install the latest release on macOS or Linux:

curl --proto '=https' --tlsv1.2 -LsSf \
  https://github.com/runrly/zwd/releases/latest/download/zwd-installer.sh | sh

Install the latest release on Windows PowerShell:

powershell -ExecutionPolicy Bypass -c "irm https://github.com/runrly/zwd/releases/latest/download/zwd-installer.ps1 | iex"

Installers place the zwd binary under Cargo's bin directory by default. Make sure that directory is on your PATH.

You can also download platform archives from GitHub Releases. Release artifacts include SHA256 checksums.

Quick Start

Create a registered workspace from two project folders:

zwd create ../api ../web --name work

Open it in Zed:

zwd open work

List registered workspaces:

zwd list

Add another folder later:

zwd add ../docs --workspace work

Remove a folder without deleting the project directory:

zwd remove ../docs --workspace work

Usage

The public command is zwd, short for Zed Workspace Dock. The repository, Cargo package, release assets, and managed state directories use the short zwd name.

Create a registered workspace with a generated name:

zwd create ../api ../web

The command prints the real .code-workspace path created under the user config directory, for example:

~/Library/Application Support/zwd/workspaces/ws-abcd0001020304ff.code-workspace

Create a workspace file in a specific output directory:

zwd create ../api ../web --name work --output ../workspaces

Create a workspace that opens folders directly instead of a dock root:

zwd create ../api ../web --name work --mode folders

Open a workspace file by path:

zwd open ../workspaces/work.code-workspace

Force folder mode for one run:

zwd open ../workspaces/work.code-workspace --mode folders

Reuse an existing Zed window:

zwd open work --reuse

Use a custom Zed executable, useful for tests or alternate installs:

zwd open work --zed-bin /Applications/Zed.app/Contents/MacOS/cli

For a simple argument such as work, registered workspaces take precedence over a same-name file or directory in the current directory. Use an explicit path such as ./work.code-workspace when you want to open a local file.

Maintain a Workspace

Add one or more folders to a workspace:

zwd add ../api ../web --workspace work

Remove one or more folders by canonical path. The projects themselves are never deleted:

zwd remove ../legacy ../docs --workspace work

When the current directory is the root of a managed dock, add and remove infer the owning workspace from .zwd-lock.json, so the flag is optional:

zwd add ../docs
zwd remove ../legacy

Both commands are idempotent. Adding an existing folder or removing an absent one reports that state without changing the workspace or dock. A dock that already exists is reconciled immediately and incrementally; a dock that does not exist is still materialized by the next zwd open in symlink mode.

Synchronize a dock without opening Zed:

zwd sync work
zwd sync ./work.code-workspace
# From the root of a managed dock:
zwd sync

open and sync recover missing managed links and reconcile changes from the .code-workspace configuration. Correct links remain in place. Files, directories such as .dirac, and manually added symlinks are preserved without being adopted into the lock. A changed managed symlink target, a managed link replaced by a real file/directory, or an unmanaged entry occupying a required link name causes an error before link changes. Restore or move that conflicting entry manually before retrying.

sync creates an absent dock for a symlink-mode workspace. For a folder-mode workspace it synchronizes an existing dock, or succeeds with a message when there is no dock. Workspace inference uses only the lock in the current dock root; it does not search parent directories. The workspace file remains the source of truth, so synchronization does not restore projects removed from that file.

Inspect a workspace and its dock health:

zwd status work

status reports the workspace path, registration, mode, resolved folders, and dock state without changing files. Extra dock content is healthy; missing managed links, changed destinations, stale lock membership, unresolvable folders, or invalid ownership are unhealthy. Use sync to recover missing links or reconcile configuration changes. A missing dock is normal before the first open or sync in symlink mode.

Preview workspace deletion, then confirm it:

zwd delete work
zwd delete work --force

delete accepts a registered name or an explicit .code-workspace path. Without --force, it previews the workspace file and owned dock and states that all local dock contents would be removed. With --force, it removes the entire validated, lock-owned dock, including extra files, nested directories, and manual symlinks, then removes the workspace file. Symlinks are unlinked without following their targets, so linked project folders are preserved. Files stored only inside the dock are deleted. The command does not close applications using the dock and refuses to delete from the dock root or a real subdirectory beneath it. Missing project targets do not prevent deletion. Filesystem errors can interrupt deletion; the workspace file is kept if dock removal fails.

Zed Tasks

Install global Zed tasks:

zwd install

By default, this writes the global Zed tasks file at ~/.config/zed/tasks.json. The installer reads templates from resources/zed-tasks.json, injects the absolute command path, and merges by task label without duplicating managed tasks.

Install tasks with an explicit binary path:

zwd install --command /usr/local/bin/zwd

Install into an explicit tasks file:

zwd install --tasks-path ~/.config/zed/tasks.json

Installed tasks use $ZED_FILE. Run them while a .code-workspace file is open or selected in Zed.

Workspace Files

Zed Workspace Dock accepts strict JSON .code-workspace files:

{
  "folders": [
    { "name": "api", "path": "../api" },
    { "path": "../web" }
  ],
  "zwd": {
    "mode": "symlink"
  }
}

Supported modes are:

  • symlink: build and open a managed dock root.
  • folders: pass resolved project folder paths directly to Zed.

If zwd exists, mode is required. If folders is missing, runtime parsing treats it as an empty list.

Important

Workspaces from older versions that use zed-dock must be migrated manually. Rename the top-level zed-dock object to zwd, and rename dock files from .zed-dock.json to .zwd-lock.json.

Registered workspaces are stored under the user config directory at zwd/workspaces/. Workspaces created with --output <dir> are standalone files in that directory and are opened by path.

The create command accepts one or more folder paths as positional arguments. It writes symlink mode unless --mode folders is passed. Created workspaces store canonical absolute folder paths resolved from the current working directory.

add and remove preserve all unrelated JSON properties in an existing workspace file, including Zed settings and tasks, while changing only folders. remove may leave folders empty; use delete when the workspace file and its dock should be removed.

Schemas

JSON Schemas are published under resources/schemas/ using JSON Schema Draft 2020-12:

  • resources/schemas/code-workspace.schema.json describes the .code-workspace shape used by this tool.
  • resources/schemas/zwd-lock.schema.json describes the internal .zwd-lock.json lock stored inside managed docks.

The schemas are documentation, editor, and test resources. Runtime parsing still uses the Rust data model and explicit validation errors.

Safety

  • Dock directories live under the platform cache directory at zwd/docks/.
  • Each managed dock contains .zwd-lock.json.
  • Rebuilds modify only lock-owned docks.
  • Incremental edits reconcile only changed symlinks in an existing owned dock.
  • Existing dock directories without a valid lock abort.
  • Extra files and manual symlinks are preserved during opening and reconciliation; delete --force removes all local dock contents.
  • Existing dock roots must be real directories and locks must be regular files, not symlinks.
  • Managed link conflicts abort synchronization before any link changes.
  • Project folders are symlinked, not copied.
  • Symlink targets are not deleted or mutated.
  • folders[].name must be one filesystem entry name, not a path.
  • folders[].name cannot use reserved dock metadata names such as .zwd-lock.json.
  • Registered workspace names must be one filesystem entry name without .code-workspace; open accepts the name with or without that extension.
  • Registered workspace creation does not overwrite an existing workspace unless --force is passed.
  • delete --force never bypasses dock ownership checks; it confirms deletion of the entire owned dock.

Development

Use the pinned Rust toolchain from rust-toolchain.toml. If the host does not already have the toolchain and support packages, use the repo Devbox environment:

devbox shell

Or run any command through Devbox without entering a shell:

devbox run -- cargo check --all-targets --locked

Run the core checks:

cargo fmt --all -- --check
cargo check --all-targets --locked
cargo test --locked
cargo clippy --all-targets --all-features --locked -- -D warnings

Build locally:

cargo build

Build a production binary:

cargo build --release --locked

The release binary is written to target/release/zwd.

Release Flow

This project uses Release PRs:

  1. Merge feature and fix PRs into main.
  2. release-plz opens or updates the sole Release PR on release-plz/main with the next version and changelog.
  3. Merge the Release PR; automation creates the signed vX.Y.Z tag.
  4. A maintainer manually dispatches the Release workflow for that tag.
  5. The protected release-publication environment requires approval before cargo-dist builds release archives, installers, checksums, attestations, and the GitHub Release.

To publish a tag, open Actions → Release → Run workflow, select main, and enter its vX.Y.Z tag. Then approve the release-publication environment.

Before the first release, configure the release-signing environment with the RUNRLY_ECHO_SIGNING_PRIVATE_KEY secret. Register the matching public key as an SSH signing key on the maintainer's GitHub account, where echo@runrly.dev is a verified email. Release tags use the identity runrly-echo <echo@runrly.dev>; the private key is not available to the manual publication workflow.

Versioning follows CLI SemVer. The package is currently publish = false, so distribution is through GitHub Release artifacts rather than crates.io.

References

This project was informed by:

No source code from those projects is copied here. If that changes later, keep the required license notices with the copied code.

About

Create and open Zed .code-workspace files through folder mode or a marker-protected symlink dock.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

6 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages