URDF
URDF language support for Zed with syntax highlighting, outline, and completions.
How to install
With Forge Super installed, the button above opens the app on this extension, where you press Install. Nothing is installed until you do.
You can also open the Extensions panel in the app and search for URDF. The extension's id is urdf.
Don't have Forge Super yet? Download it here.
README
From the extension's repository, written by its authors and not by Mentenaz. See the source.
URDF for Zed
URDF language support for Zed with:
- Syntax highlighting
- Outline / structure view
- Auto indentation
- Context-aware completions for common URDF tags, attributes, and values
This extension targets .urdf files and builds on top of the XML Tree-sitter grammar plus an external URDF language server.
Features
- Recognizes
.urdffiles as theURDFlanguage - Reuses the XML Tree-sitter grammar for parsing
- Provides syntax highlighting through Tree-sitter queries
- Provides outline support for URDF/XML elements
- Shows
namecontext in outline entries forrobot,link, andjoint - Provides completions for common URDF tags such as:
robotlinkjointvisualcollisioninertialgeometryoriginparentchildaxislimitmaterialmesh
- Provides completions for common URDF attributes and values
- Supports both block-style and self-closing completions for tags like
linkandmaterial
Installation
For normal users:
- Install the extension in Zed
- Open a
.urdffile - The extension will look for a language server binary whose version exactly matches the extension version
- If that exact-version binary is not already cached, the extension downloads the matching GitHub Release asset for the same version
This extension intentionally uses a strict version lock between the extension and the language server.
That means:
- extension version
0.1.0only accepts language server release tagv0.1.0 - extension version
0.1.1only accepts language server release tagv0.1.1 - the extension does not use the latest release automatically
- the extension does not silently fall back to a different installed server version
Version Lock Policy
The repository follows these rules:
Cargo.tomlversionextension.tomlversionurdf-language-server/Cargo.tomlversion- Git tag name without the leading
v
must all be identical.
Examples:
- extension version:
0.1.0 - language server crate version:
0.1.0 - Git tag:
v0.1.0
At runtime, the extension downloads only the release with tag v0.1.0 when the extension version is 0.1.0.
Release Assets
Expected release asset names:
urdf-language-server-vX.Y.Z-x86_64-unknown-linux-musl.tar.gzurdf-language-server-vX.Y.Z-x86_64-apple-darwin.tar.gzurdf-language-server-vX.Y.Z-aarch64-apple-darwin.tar.gzurdf-language-server-vX.Y.Z-x86_64-pc-windows-msvc.zip
Each archive must contain the executable at the archive root:
urdf-language-serverurdf-language-server.exeon Windows
Development
Prerequisites
Install Rust with rustup.
Install as a Dev Extension in Zed
- Open Zed
- Open the command palette
- Run
zed: install dev extension - Select this repository folder
After changing the extension, open the Extensions page and click Rebuild for the dev extension.
Local Testing Without GitHub Release
You do not need to publish a GitHub Release every time you modify the language server during development.
With the strict version-locked setup used by this extension, the runtime behavior is:
- The extension first checks whether a language server binary for the exact same version already exists in the local versioned cache directory
- Only if that exact-version binary is missing does it try to download the matching GitHub Release asset for the same version tag
That means local development can use a manually built binary, as long as:
- the extension version and language server version are the same
- the binary is placed at the expected versioned cache path
Keep versions in sync
Before local testing, make sure these versions are identical:
Cargo.tomlextension.tomlurdf-language-server/Cargo.toml
For example, if the version is 0.1.0, then all three files should use 0.1.0.
Build the language server locally
From the repository root:
cargo build --manifest-path ./urdf-language-server/Cargo.toml --release
Put the binary into the expected local cache directory
Create the versioned cache directory expected by the extension:
Linux:
~/.local/share/zed/extensions/work/.zed-urdf/<version>/
macOS:
~/Library/Application Support/zed/extensions/work/.zed-urdf/<version>/
Windows:
%LOCALAPPDATA%\Zed\extensions\work\.zed-urdf\<version>\
Then copy the locally built binary into that directory.
Linux
If you build for the default host target:
ZED_EXT_DIR="$HOME/.local/share/zed/extensions/work/urdf/.zed-urdf/0.1.0"
mkdir -p "$ZED_EXT_DIR"
cp urdf-language-server/target/release/urdf-language-server "$ZED_EXT_DIR/urdf-language-server"
chmod +x "$ZED_EXT_DIR/urdf-language-server"
If you explicitly build a target triple, your output path may instead look like this:
ZED_EXT_DIR="$HOME/.local/share/zed/extensions/work/urdf/.zed-urdf/0.1.0"
mkdir -p "$ZED_EXT_DIR"
cp urdf-language-server/target/x86_64-unknown-linux-gnu/release/urdf-language-server "$ZED_EXT_DIR/urdf-language-server"
chmod +x "$ZED_EXT_DIR/urdf-language-server"
macOS
ZED_EXT_DIR="$HOME/Library/Application Support/zed/extensions/work/urdf/.zed-urdf/0.1.0"
mkdir -p "$ZED_EXT_DIR"
cp urdf-language-server/target/release/urdf-language-server "$ZED_EXT_DIR/urdf-language-server"
chmod +x "$ZED_EXT_DIR/urdf-language-server"
Windows (PowerShell)
$ZedExtDir = "$env:LOCALAPPDATA\Zed\extensions\work\.zed-urdf\0.1.0"
New-Item -ItemType Directory -Force -Path $ZedExtDir | Out-Null
Copy-Item "urdf-language-server\target\release\urdf-language-server.exe" "$ZedExtDir\urdf-language-server.exe"
Replace 0.1.0 with your actual current extension version.
Recommended local test workflow after changing the language server
When you modify urdf-language-server/src/main.rs:
- Keep all versions unchanged if you are just testing local behavior
- Run the local release build
- Copy the new binary into
.zed-urdf/<version>/ - Rebuild the dev extension in Zed
- Reopen a
.urdffile and verify completions
Testing a version bump locally
If you want to test a new version locally, such as moving from 0.1.0 to 0.1.1:
-
Update these files to
0.1.1:Cargo.tomlextension.tomlurdf-language-server/Cargo.toml
-
Build the language server again
-
Copy the binary into
.zed-urdf/0.1.1/ -
Rebuild the dev extension in Zed
The extension will then use only the 0.1.1 binary and will not reuse the old 0.1.0 cache.
When is GitHub Release actually needed?
A GitHub Release is only needed when you want to test the real published download path:
- remove the local cached binary for the current version
- keep the same version
- create the matching Git tag such as
v0.1.0 - publish the release assets
- let the extension download that exact-version asset automatically
Publishing Notes
This repository keeps the language server source code, but the published Zed extension does not ship the server binary inside the extension package.
Instead:
- GitHub Actions builds versioned language server binaries
- those binaries are uploaded as GitHub Release assets
- the extension downloads only the asset whose tag exactly matches the extension version
Troubleshooting
If the extension does not seem to work:
- open
Zed.logusingzed: open log - or launch Zed from the command line with:
zed --foreground
This usually shows more detailed extension and language server logs during development.
You may also want to check:
- whether the three version fields are exactly the same
- whether the local binary exists under
.zed-urdf/<version>/ - whether the binary name is correct for your platform
- whether the binary is executable on Unix-like systems
Project Structure
.
├── .github/
│ └── workflows/
│ ├── check-version-sync.yml
│ └── release-language-server.yml
├── README.md
├── extension.toml
├── Cargo.toml
├── src/
│ └── lib.rs
├── languages/
│ └── urdf/
│ ├── config.toml
│ ├── highlights.scm
│ ├── indents.scm
│ └── outline.scm
└── urdf-language-server/
├── Cargo.toml
└── src/
└── main.rs
Example
<?xml version="1.0"?>
<robot name="demo_robot">
<link name="base_link" />
<link name="arm_link">
<visual>
<geometry>
<box size="1 1 1" />
</geometry>
</visual>
</link>
<joint name="base_to_arm" type="revolute">
<parent link="base_link" />
<child link="arm_link" />
<origin xyz="0 0 0.1" rpy="0 0 0" />
<axis xyz="0 0 1" />
<limit lower="-1.57" upper="1.57" effort="100" velocity="1.0" />
</joint>
</robot>
Notes
- This extension currently uses the XML grammar for parsing URDF documents
- Completions are provided by the external custom URDF language server
- The completion engine is designed specifically for common URDF authoring workflows, rather than full XML Schema/XSD validation
Acknowledgements
This project builds on and draws inspiration from:
Many thanks to the maintainers and contributors of those projects.
License
This project is licensed under the Apache License 2.0.