| languages/mcf | ||
| mcf-ls | ||
| snippets | ||
| src | ||
| .gitignore | ||
| Cargo.toml | ||
| extension.toml | ||
| LICENSE | ||
| README.md | ||
MCF — Malasaur Compose Format — Zed Extension
A Zed extension that adds full MCF support to compose.yml files.
What is MCF?
MCF (Malasaur Compose Format) is an opinionated convention for Docker Compose files that enforces portability, consistency, and explicit configuration. See the spec for details.
Features
| Feature | Description |
|---|---|
| Diagnostics | Real-time error/warning highlighting for every MCF rule violation |
| Formatting | Auto-formats the file to MCF field order and normalises network syntax |
| Completions | Service scaffolding, volume presets, CDP label templates |
| Snippets | Zed-level snippets for common MCF patterns |
| Create paths | Command to mkdir -p all local bind-mount directories |
| Apply template | Fetch and apply stack templates from git repositories |
Diagnostics (errors & warnings)
The extension reports errors for every MCF rule violation, including:
- Service fields out of MCF order (
image,container_name,restart,ports,volumes,environment,<additional_config>,group_add,networks,labels) - Missing required fields (
image,container_name,restart) container_namenot matching service namerestartnot set tounless-stoppedenvironment:written as list form instead of mapping formnetworks:written as block form when onlycaddyis used (must benetworks: [caddy])- Service joins
caddynetwork but has no CDP labels, or vice versa caddynetwork used but not declaredexternal: truein top-levelnetworks:- Named volumes used but not declared in top-level
volumes: - Ports 80 or 443 exposed on the host
- Invalid service name format (must be
lowercase,letters-digits-hyphens)
Formatting
Trigger formatting with Format Document (⌥⇧F / Alt+Shift+F).
The MCF formatter:
- Reorders every service's fields to the canonical MCF order
- Converts
networks:block form tonetworks: [caddy]when only caddy is used - Normalises
group_add:to short inline form[gid] - Reconstructs the entire document with consistent 2-space indentation
Note: Comments are not preserved by the MCF formatter. This is a known limitation of v0.1.
Commands (Command Palette)
| Command | Palette name |
|---|---|
| Create local volume directories | MCF: Create local volume directories (mkdir -p) |
| Browse templates | MCF: Browse and apply stack template |
Create paths runs mkdir -p for every ./… bind-mount path in the compose file. It will refuse to run if there are any MCF validation errors.
Apply template clones the default template repository (https://git.sunet.uk/malasaur/mcf-templates) and any user-configured repos, then lists available templates. Use the mcf.apply-template command with the template name to replace the current buffer with the template.
Completions & Snippets
- Typing a service name at indent 2 inside
services:→ offers to scaffold a full MCF service - Inside a service's
volumes:list → offers common volume presets (./data:/data,./config:/config,./db:/db,cache:/cache, etc.) - Trigger Zed snippets with prefixes:
mcf-service,mcf-service-cdp,anubis,vol-data,vol-config,vol-db,vol-cache,mcf-networks-caddy,mcf-labels, …
Installation
1. Clone this extension
git clone https://github.com/malasaur/mcf-zed ~/.config/zed/extensions/mcf
2. Install the language server
cargo install --path ~/.config/zed/extensions/mcf/mcf-ls
This installs mcf-ls into Cargo's bin directory (usually ~/.cargo/bin), which the extension looks up via your PATH.
You can verify that Zed should be able to find it with:
which mcf-ls
If that prints nothing, add Cargo's bin directory to your shell config:
export PATH="$HOME/.cargo/bin:$PATH"
3. Install as a dev extension in Zed
Open the Zed Extensions page (zed: open extensions), click Install Dev Extension, and select the mcf-zed directory.
4. Configure file-type association
Add the following to your Zed settings.json (zed: open settings):
{
"file_types": {
"MCF": ["**/compose.yml"]
}
}
This ensures the MCF language and language server activate only for files named exactly compose.yml. Files named docker-compose.yml, compose.yaml, etc. will continue to use the Docker Compose extension as normal.
Optional: Add template repositories
Add additional MCF template repositories in your Zed settings.json:
{
"lsp": {
"mcf-ls": {
"initialization_options": {
"templateRepositories": [
"https://git.sunet.uk/malasaur/mcf-templates",
"https://github.com/your-org/mcf-templates"
]
}
}
}
}
Template repositories must contain a templates/ directory with:
<service>.yml— the compose template (supports$1,$2tab-stop comments)<service>.svg/.png— optional icon
MCF Field Order Reference
services:
<service>:
image:
container_name: # must match service name
restart: unless-stopped
ports:
volumes:
environment: # mapping form only
# <additional_config>
group_add: [<gid>] # short inline form
networks: [caddy] # inline form when only caddy
labels:
caddy: ${DOMAIN}
caddy.reverse_proxy: "{{upstreams 80}}"
networks:
caddy:
external: true
volumes:
cache:
License
MIT — see LICENSE.