Skip to main content

Overview

Glass features a comprehensive extension system that allows developers to add new languages, themes, language servers, debuggers, and custom functionality. Extensions are built using WebAssembly (WASM) for security and cross-platform compatibility.

Extension Manifest

Basic Structure

# extension.toml
id = "my-extension"
name = "My Extension"
version = "0.1.0"
schema_version = 1
description = "A custom extension for Glass"
repository = "https://github.com/user/my-extension"
authors = ["Your Name <[email protected]>"]

Manifest Fields

// From crates/extension/src/extension_manifest.rs
pub struct ExtensionManifest {
    pub id: Arc<str>,
    pub name: String,
    pub version: Arc<str>,
    pub schema_version: SchemaVersion,
    pub description: Option<String>,
    pub repository: Option<String>,
    pub authors: Vec<String>,
    // ...
}

Required Fields

  • id: Unique extension identifier
  • name: Human-readable name
  • version: Semantic version
  • schema_version: Manifest schema version

Optional Fields

  • description: Extension description
  • repository: Source code URL
  • authors: Extension authors

Extension Capabilities

Provided Features

pub fn provides(&self) -> BTreeSet<ExtensionProvides> {
    // Returns set of features this extension provides
}

pub enum ExtensionProvides {
    Themes,
    IconThemes,
    Languages,
    Grammars,
    LanguageServers,
    ContextServers,
    AgentServers,
    Snippets,
    DebugAdapters,
}
Extensions can provide:
  • Languages: Language definitions
  • Grammars: Tree-sitter grammars for syntax highlighting
  • Snippets: Code snippet libraries

Language Support

Adding a Language

# extension.toml
[[languages]]
path = "languages/rust.json"
// languages/rust.json
{
  "name": "Rust",
  "grammar": "rust",
  "path_suffixes": ["rs"],
  "line_comments": ["// "],
  "block_comment": ["/* ", " */"]
}

Grammar Configuration

[grammars.rust]
repository = "https://github.com/tree-sitter/tree-sitter-rust"
commit = "v0.20.4"
Tree-sitter grammars provide:
  • Syntax highlighting
  • Code folding
  • Structural navigation
  • Smart selection

Language Server Integration

Language Server Configuration

[language_servers.rust-analyzer]
name = "rust-analyzer"
languages = ["Rust"]

Extension API

// From crates/extension/src/extension.rs
async fn language_server_command(
    &self,
    language_server_id: LanguageServerName,
    language_name: LanguageName,
    worktree: Arc<dyn WorktreeDelegate>,
) -> Result<Command>

async fn language_server_initialization_options(
    &self,
    language_server_id: LanguageServerName,
    language_name: LanguageName,
    worktree: Arc<dyn WorktreeDelegate>,
) -> Result<Option<String>>
Implement language server integration:
1

Define Server

Specify the language server in the manifest
2

Provide Command

Return the command to launch the server
3

Configure Options

Set initialization and workspace options
4

Customize Labels

Optionally customize completion and symbol labels

Advanced Configuration

async fn language_server_workspace_configuration(
    &self,
    language_server_id: LanguageServerName,
    worktree: Arc<dyn WorktreeDelegate>,
) -> Result<Option<String>>

async fn language_server_additional_initialization_options(
    &self,
    language_server_id: LanguageServerName,
    target_language_server_id: LanguageServerName,
    worktree: Arc<dyn WorktreeDelegate>,
) -> Result<Option<String>>

Themes

Theme Structure

themes = ["themes/my-theme.json"]
icon_themes = ["icon-themes/my-icons.json"]
Themes define:
  • Editor color schemes
  • Syntax highlighting colors
  • UI element colors
  • Terminal colors

Icon Themes

Customize file and folder icons:
  • File type associations
  • Folder icons
  • Special file indicators

Snippets

Snippet Configuration

snippets = "snippets"
# or
snippets = ["snippets/rust.json", "snippets/common.json"]
pub enum ExtensionSnippets {
    Single(PathBuf),
    Multiple(Vec<PathBuf>),
}
Provide code snippets for quick insertion:
  • Language-specific snippets
  • Global snippets
  • Tab stop navigation
  • Variable substitution

Debug Adapters

Debug Adapter Protocol (DAP)

[debug_adapters.lldb]
name = "lldb-dap"
languages = ["Rust", "C", "C++"]
async fn get_dap_binary(
    &self,
    dap_name: Arc<str>,
    config: DebugTaskDefinition,
    user_installed_path: Option<PathBuf>,
    worktree: Arc<dyn WorktreeDelegate>,
) -> Result<DebugAdapterBinary>

async fn dap_request_kind(
    &self,
    dap_name: Arc<str>,
    config: serde_json::Value,
) -> Result<StartDebuggingRequestArgumentsRequest>
Integrate debuggers:

Setup

  • Specify debug adapter binary
  • Configure launch parameters
  • Map to supported languages

Features

  • Breakpoints
  • Variable inspection
  • Step debugging
  • Call stack navigation

Slash Commands

Custom Slash Commands

[slash_commands.my-command]
name = "my-command"
description = "Custom slash command"
async fn run_slash_command(
    &self,
    command: SlashCommand,
    arguments: Vec<String>,
    worktree: Option<Arc<dyn WorktreeDelegate>>,
) -> Result<SlashCommandOutput>

async fn complete_slash_command_argument(
    &self,
    command: SlashCommand,
    arguments: Vec<String>,
) -> Result<Vec<SlashCommandArgumentCompletion>>
Create custom commands for the AI assistant:
  • Define command behavior
  • Provide argument completion
  • Access worktree context
  • Return structured output

Context Servers

Context Server Configuration

[context_servers.my-context]
command = "./context-server"
async fn context_server_command(
    &self,
    context_server_id: Arc<str>,
    project: Arc<dyn ProjectDelegate>,
) -> Result<Command>

async fn context_server_configuration(
    &self,
    context_server_id: Arc<str>,
    project: Arc<dyn ProjectDelegate>,
) -> Result<Option<ContextServerConfiguration>>
Provide external context to the AI assistant:
  • Database schemas
  • API documentation
  • Project-specific knowledge
  • Real-time data sources

Security and Capabilities

Process Execution

pub fn allow_exec(
    &self,
    desired_command: &str,
    desired_args: &[impl AsRef<str> + std::fmt::Debug],
) -> Result<()>

Capability Declaration

[[capabilities]]
type = "process-exec"
command = "node"
args = ["--version"]
Extensions must explicitly declare process execution capabilities in their manifest for security.
Supported capabilities:
  • process-exec: Execute external processes
  • npm-install-package: Install npm packages
  • download-file: Download files from URLs

Capability Types

// From extension capabilities
pub enum ExtensionCapability {
    ProcessExec(ProcessExecCapability),
    NpmInstallPackage(NpmInstallPackageCapability),
    DownloadFile(DownloadFileCapability),
}

Building Extensions

WASM Compilation

Extensions are compiled to WebAssembly:
pub fn parse_wasm_extension_version(
    extension_id: &str,
    wasm_bytes: &[u8]
) -> Result<Version>

API Versioning

Extensions declare their API version:
// Custom section: zed:api-version
// Contains the API version the extension was built against
Glass checks the API version to ensure compatibility between the extension and the editor.

Extension Lifecycle

Loading Extensions

1

Discovery

Glass discovers extensions in the extensions directory
2

Validation

Manifest and WASM are validated
3

Initialization

Extension is loaded and initialized
4

Registration

Features are registered with appropriate systems

Extension Events

// From extension_events
pub fn init(cx: &mut App)
Extensions can respond to:
  • Installation and uninstallation
  • Enable/disable events
  • Configuration changes
  • Project open/close

Best Practices

Development Guidelines

Manifest

  • Use semantic versioning
  • Declare all capabilities needed
  • Provide clear descriptions
  • Include repository URL

Code

  • Handle errors gracefully
  • Minimize WASM size
  • Cache expensive operations
  • Document extension API usage

Testing

  • Test with different project structures
  • Verify language server integration
  • Test theme in light and dark modes
  • Validate capability declarations
Use the extension builder to scaffold new extensions with proper structure and boilerplate.

Publishing Extensions

Once your extension is ready:
  1. Ensure all manifest fields are complete
  2. Test thoroughly in development
  3. Tag a release with proper versioning
  4. Submit to the Glass extension registry
  5. Maintain compatibility with API changes

Build docs developers (and LLMs) love