zed-editor
Configure, customize, and manage the Zed code editor. Use when the user wants to modify Zed keybindings, settings, tasks, or extensions — especially for chaining editor actions via workspace::SendKeystrokes, creating custom workflows, or opening projects in Zed. Also use when launching Zed from the CLI, setting up vim/helix mode bindings, or troubleshooting Zed configuration.
Best use case
zed-editor is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Configure, customize, and manage the Zed code editor. Use when the user wants to modify Zed keybindings, settings, tasks, or extensions — especially for chaining editor actions via workspace::SendKeystrokes, creating custom workflows, or opening projects in Zed. Also use when launching Zed from the CLI, setting up vim/helix mode bindings, or troubleshooting Zed configuration.
Teams using zed-editor should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/zed-editor/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How zed-editor Compares
| Feature / Agent | zed-editor | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Configure, customize, and manage the Zed code editor. Use when the user wants to modify Zed keybindings, settings, tasks, or extensions — especially for chaining editor actions via workspace::SendKeystrokes, creating custom workflows, or opening projects in Zed. Also use when launching Zed from the CLI, setting up vim/helix mode bindings, or troubleshooting Zed configuration.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Zed Editor Skill
Configure and customize the Zed code editor by reading and writing its JSON config files, managing keybindings (including `workspace::SendKeystrokes` command chaining), defining tasks, and launching Zed via CLI.
## Config File Locations
### macOS
```
~/Library/Application Support/Zed/settings.json # Editor settings
~/Library/Application Support/Zed/keymap.json # Keybindings
~/Library/Application Support/Zed/tasks.json # Global tasks
```
### Linux
```
~/.config/zed/settings.json
~/.config/zed/keymap.json
~/.config/zed/tasks.json
```
### Per-project overrides
```
<project>/.zed/settings.json
<project>/.zed/tasks.json
```
**Detect OS first** — check `uname` to determine which paths to use.
---
## Core Workflow
1. **Detect OS** to resolve config paths
2. **Read existing config** before making any changes (preserve user's work)
3. **Validate JSON** — all Zed configs are JSON arrays or objects; malformed JSON will silently break the editor config
4. **Write changes** using careful JSON merging — don't clobber existing bindings/settings
5. **Verify** the file is valid JSON after writing
### Reading Config Safely
```bash
# macOS
CONFIG_DIR="$HOME/Library/Application Support/Zed"
# Linux
CONFIG_DIR="$HOME/.config/zed"
# Read keymap (may not exist yet)
cat "$CONFIG_DIR/keymap.json" 2>/dev/null || echo "[]"
# Read settings
cat "$CONFIG_DIR/settings.json" 2>/dev/null || echo "{}"
```
---
## Keybindings (keymap.json)
The keymap file is a JSON **array** of binding objects. Each object can have an optional `context` and a required `bindings` map.
### Structure
```json
[
{
"context": "Editor && vim_mode == normal",
"bindings": {
"key-combo": "action::Name",
"key-combo": ["action::Name", { "param": "value" }]
}
}
]
```
### Key Syntax
Keys use modifier-key format separated by `-`:
- Modifiers: `cmd`, `ctrl`, `alt`, `shift`, `fn`
- Special keys: `up`, `down`, `left`, `right`, `enter`, `escape`, `tab`, `space`, `backspace`, `delete`, `home`, `end`, `pageup`, `pagedown`
- Letters/numbers: `a`-`z`, `0`-`9`
- Multi-key sequences: `"g e"` (space-separated, typed in sequence)
Examples: `"cmd-shift-p"`, `"ctrl-w h"`, `"alt-down"`, `"g e"`
### Context Expressions
Contexts scope bindings to specific UI states. Use `&&` for AND, `||` for OR, `!` for NOT, `>` for ancestor matching.
Common contexts:
- `Editor` — any editor pane
- `Terminal` — terminal panel
- `ProjectPanel` — file tree
- `Dock` — any dock panel
- `vim_mode == normal` / `insert` / `visual` — vim mode states
- `VimControl` — normal + visual modes combined
- `menu` — autocomplete/palette is open
- `EmptyPane` — no file open
Examples:
```json
"context": "Editor && vim_mode == normal && !menu"
"context": "Terminal"
"context": "VimControl && !menu"
```
---
## workspace::SendKeystrokes — Command Chaining
This is Zed's most powerful keybinding primitive. It dispatches a sequence of keystrokes synchronously, letting you chain multiple actions into a single keybinding **without writing an extension**.
### Syntax
```json
"key": ["workspace::SendKeystrokes", "keystroke1 keystroke2 keystroke3"]
```
Keystrokes are space-separated. Each keystroke uses the same modifier-key syntax as keybinding keys.
### Important Constraints
- **Synchronous only**: SendKeystrokes dispatches all keys before any async operation completes. You CANNOT rely on async results (opening files, language server responses, command palette searches) between keystrokes.
- **No cross-view chaining**: You cannot send keys to a view that opens as a result of a previous keystroke in the same sequence.
- Async operations include: opening command palette, language server communication, changing buffer language, network requests.
### Patterns
**Chain copy + deselect:**
```json
"alt-w": ["workspace::SendKeystrokes", "cmd-c escape"]
```
**Move down N lines:**
```json
"alt-down": ["workspace::SendKeystrokes", "down down down down"]
```
**Select syntax node + copy + undo selection:**
```json
"cmd-alt-c": [
"workspace::SendKeystrokes",
"ctrl-shift-right ctrl-shift-right ctrl-shift-right cmd-c ctrl-shift-left ctrl-shift-left ctrl-shift-left"
]
```
**Vim yank to end of line (neovim style):**
```json
{
"context": "vim_mode == normal && !menu",
"bindings": {
"shift-y": ["workspace::SendKeystrokes", "y $"]
}
}
```
**Vim insert mode escape via jk:**
```json
{
"context": "Editor && vim_mode == insert",
"bindings": {
"j k": ["workspace::SendKeystrokes", "escape"]
}
}
```
### Strategy for Building SendKeystrokes Chains
1. First identify the individual actions needed (use `zed: open default keymap` or the All Actions reference)
2. Find the existing keybindings for each action
3. Chain those key combos in a single SendKeystrokes string
4. Test that none of the intermediate actions are async
---
## Common Actions Reference
### Editor Actions
| Action | Description |
|--------|-------------|
| `editor::Copy` | Copy selection |
| `editor::Cut` | Cut selection |
| `editor::Paste` | Paste |
| `editor::Undo` | Undo |
| `editor::Redo` | Redo |
| `editor::SelectAll` | Select all |
| `editor::Format` | Format document |
| `editor::ToggleComments` | Toggle line comments |
| `editor::MoveLineUp` | Move current line up |
| `editor::MoveLineDown` | Move current line down |
| `editor::DuplicateLineDown` | Duplicate line |
| `editor::SelectLargerSyntaxNode` | Expand selection to syntax |
| `editor::SelectSmallerSyntaxNode` | Shrink selection |
| `editor::GoToDefinition` | Go to definition |
| `editor::GoToDeclaration` | Go to declaration |
| `editor::GoToImplementation` | Go to implementation |
| `editor::Rename` | Rename symbol |
| `editor::ToggleCodeActions` | Show code actions |
| `editor::Newline` | Insert newline |
| `editor::Tab` | Insert tab/indent |
| `editor::Outdent` | Outdent |
| `editor::FoldAll` | Fold all |
| `editor::UnfoldAll` | Unfold all |
### Workspace Actions
| Action | Description |
|--------|-------------|
| `workspace::NewFile` | New file |
| `workspace::Save` | Save |
| `workspace::SaveAll` | Save all |
| `workspace::Open` | Open file dialog |
| `workspace::ToggleLeftDock` | Toggle left dock |
| `workspace::ToggleRightDock` | Toggle right dock |
| `workspace::ToggleBottomDock` | Toggle bottom dock |
| `workspace::ActivateNextPane` | Focus next pane |
| `workspace::ActivatePreviousPane` | Focus previous pane |
| `workspace::SendKeystrokes` | Chain keystrokes |
### Navigation
| Action | Description |
|--------|-------------|
| `file_finder::Toggle` | Open file finder |
| `project_symbols::Toggle` | Open symbol search |
| `buffer_search::Deploy` | Find in file |
| `project_search::ToggleFocus` | Find in project |
| `outline::Toggle` | Open outline view |
| `go_to_line::Toggle` | Go to line number |
| `tab_switcher::Toggle` | Switch tabs |
| `diagnostics::Deploy` | Open diagnostics |
### Terminal
| Action | Description |
|--------|-------------|
| `terminal_panel::ToggleFocus` | Toggle/focus terminal |
| `workspace::NewTerminal` | New terminal tab |
### Git
| Action | Description |
|--------|-------------|
| `git_panel::ToggleFocus` | Toggle/focus git panel |
| `git::Diff` | Open project diff view |
| `git::OpenModifiedFiles` | Open all modified files |
| `git::StageAndNext` | Stage current hunk, advance to next |
| `git::UnstageAndNext` | Unstage current hunk, advance to next |
| `git::ToggleStaged` | Toggle staged state |
| `git::Commit` | Commit staged changes |
| `git::GenerateCommitMessage` | AI-generated commit message |
| `git::Fetch` | Fetch from remote |
| `git::Push` | Push to remote |
| `git::Pull` | Pull from remote |
| `git::Restore` | Restore/undo changes |
| `editor::GoToHunk` | Navigate to next diff hunk |
| `editor::GoToPreviousHunk` | Navigate to previous diff hunk |
| `editor::ExpandAllDiffHunks` | Expand all hunks inline |
| `editor::ToggleSelectedDiffHunks` | Toggle diff for selected hunks |
---
## Settings (settings.json)
Settings is a JSON **object**. Key settings to know about:
```json
{
// Font
"buffer_font_family": "Berkeley Mono",
"buffer_font_size": 14,
// Theme
"theme": "One Dark",
// Vim/Helix mode
"vim_mode": true,
"helix_mode": false,
// Formatting
"format_on_save": "on",
"formatter": "auto",
// Tab settings
"tab_size": 2,
"hard_tabs": false,
// Soft wrap
"soft_wrap": "editor_width",
"preferred_line_length": 100,
// Autosave
"autosave": { "after_delay": { "milliseconds": 1000 } },
// Per-language overrides
"languages": {
"Python": {
"tab_size": 4,
"formatter": {
"external": {
"command": "black",
"arguments": ["-"]
}
}
}
},
// Inlay hints
"inlay_hints": {
"enabled": true
},
// Telemetry
"telemetry": {
"diagnostics": false,
"metrics": false
},
// AI / Assistant
"assistant": {
"default_model": {
"provider": "anthropic",
"model": "claude-sonnet-4-5-20250514"
}
}
}
```
### Git Settings
```json
{
"git_panel": {
"button": true,
"dock": "left",
"default_width": 360,
"status_style": "icon",
"sort_by_path": false,
"tree_view": false
},
"git": {
"git_gutter": "tracked_files",
"inline_blame": {
"enabled": true,
"delay_ms": 600,
"show_commit_summary": true
},
"hunk_style": "staged_hollow"
}
}
```
---
## Tasks (tasks.json)
Tasks let you run shell commands from Zed with access to editor context variables.
### Structure
```json
[
{
"label": "Run current file",
"command": "python $ZED_FILE",
"use_new_terminal": false,
"allow_concurrent_runs": false,
"reveal": "always"
}
]
```
### Available Environment Variables
| Variable | Value |
|----------|-------|
| `$ZED_FILE` | Absolute path of current file |
| `$ZED_FILENAME` | Filename only |
| `$ZED_DIRNAME` | Directory of current file |
| `$ZED_RELATIVE_FILE` | File path relative to project root |
| `$ZED_RELATIVE_DIR` | Directory relative to project root |
| `$ZED_STEM` | Filename without extension |
| `$ZED_ROW` | Current cursor row |
| `$ZED_COLUMN` | Current cursor column |
| `$ZED_SELECTED_TEXT` | Currently selected text |
| `$ZED_WORKTREE_ROOT` | Project root directory |
### Task Options
| Option | Values | Default |
|--------|--------|---------|
| `use_new_terminal` | `true`/`false` | `false` |
| `allow_concurrent_runs` | `true`/`false` | `false` |
| `reveal` | `"always"`, `"no_focus"`, `"never"` | `"always"` |
| `hide` | `"never"`, `"always"`, `"on_success"` | `"never"` |
| `cwd` | path string | project root |
| `env` | object of env vars | `{}` |
| `tags` | array of strings | `[]` |
---
## CLI Usage
```bash
# Open a file or directory
zed .
zed file.txt
zed project/ file.txt
# Open in new window
zed --new file.txt
# Diff two files
zed --diff old.rs new.rs
# Wait for file to close (for EDITOR usage)
zed --wait file.txt
# Open at specific line:column
zed file.txt:42
zed file.txt:42:10
# Set as default editor
export EDITOR="zed --wait"
export VISUAL="zed --wait"
# Open settings/keymap directly
zed zed://settings
zed zed://keymap
# macOS: choose release channel
zed --stable file.txt
zed --preview file.txt
zed --nightly file.txt
```
---
## Extensions
### Installed extensions location
- macOS: `~/Library/Application Support/Zed/extensions/installed/`
- Linux: `~/.local/share/zed/extensions/installed/`
Extensions are primarily managed through the Zed UI (`cmd-shift-x` / `ctrl-shift-x`), but you can inspect installed extensions via the filesystem.
---
## Workflow: Adding a Custom Keybinding
This is the most common task. Follow this procedure:
1. **Read the current keymap:**
```bash
cat "$CONFIG_DIR/keymap.json" 2>/dev/null || echo "[]"
```
2. **Parse the JSON** and check for conflicting bindings on the same key in the same context.
3. **Determine the action(s) needed.** If a single action suffices, bind directly:
```json
"cmd-shift-d": "editor::DuplicateLineDown"
```
4. **If multiple actions are needed**, use `workspace::SendKeystrokes`:
- Look up existing keybindings for each desired action
- Chain them: `["workspace::SendKeystrokes", "key1 key2 key3"]`
- Verify none are async
5. **Add the binding** to the appropriate context block (or create a new one).
6. **Write the file** and validate JSON:
```bash
python3 -c "import json; json.load(open('$CONFIG_DIR/keymap.json'))" && echo "Valid JSON"
```
---
## Workflow: Opening a Project in Zed
```bash
# Check if zed CLI is available
which zed || echo "Zed CLI not installed. Run 'Zed > Install CLI' from the app menu."
# Open project
zed /path/to/project
# Open project with specific file focused
zed /path/to/project /path/to/project/src/main.rs
```
---
## Workflow: Creating a Project Task Runner
1. Create `.zed/tasks.json` in the project root
2. Define tasks that use Zed environment variables
3. Run tasks from the command palette or bind them to keys
Example — Rust project:
```json
[
{
"label": "cargo run",
"command": "cargo run",
"cwd": "$ZED_WORKTREE_ROOT"
},
{
"label": "cargo test current file",
"command": "cargo test --lib $ZED_STEM",
"cwd": "$ZED_WORKTREE_ROOT",
"reveal": "always"
},
{
"label": "cargo clippy",
"command": "cargo clippy --all-targets",
"cwd": "$ZED_WORKTREE_ROOT",
"hide": "on_success"
}
]
```
---
## Gotchas
- **JSON only** — Zed configs don't support comments (unlike VS Code's JSONC). Strip any `//` comments before writing.
- **Array vs Object** — `keymap.json` and `tasks.json` are arrays `[]`. `settings.json` is an object `{}`.
- **Later bindings win** — If two bindings match the same context+key, the one defined later takes precedence. User bindings always override defaults.
- **SendKeystrokes is synchronous** — Don't try to chain actions that depend on async results (file opens, palette searches, LSP responses).
- **Context matching** — Contexts match at specific tree levels. `vim_mode` is set at `Editor` level, so `"Workspace && vim_mode == normal"` will never match.
- **Zed auto-reloads config** — changes to keymap.json and settings.json take effect immediately without restarting.
---
## Claude Code Integration: Change Review Workflow
This workflow bridges Claude Code (running in Warp, Ghostty, or any external terminal) with Zed for seamless change review.
### How It Works
1. A PostToolUse hook in Claude Code records every file edit to a session manifest
2. A Zed task reads the manifest and opens all changed files at the right lines
3. Git review keybindings let you cycle through diffs, stage/revert per hunk
### Setup
**Step 1: Install the hook**
Copy the hook script to a permanent location:
```bash
mkdir -p ~/.claude/hooks
cp hooks/post-tool-use.sh ~/.claude/hooks/post-tool-use.sh
chmod +x ~/.claude/hooks/post-tool-use.sh
```
**Step 2: Configure Claude Code**
Add to `~/.claude/settings.json`:
```json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "~/.claude/hooks/post-tool-use.sh"
}
]
}
]
}
}
```
**Step 3: Add the Zed tasks**
Merge the contents of `examples/tasks.json` into your global Zed tasks file:
- macOS: `~/Library/Application Support/Zed/tasks.json`
- Linux: `~/.config/zed/tasks.json`
**Step 4: Add review keybindings (optional)**
Merge `examples/keymap.json` into your Zed keymap:
- macOS: `~/Library/Application Support/Zed/keymap.json`
- Linux: `~/.config/zed/keymap.json`
**Step 5: Configure git panel (optional)**
Merge `examples/settings.json` into your Zed settings to dock the git panel on the right for a review-friendly layout.
### Usage
1. Run Claude Code in your terminal -- it edits files as usual
2. Switch to Zed
3. Run the **"Review Claude Changes"** task from the command palette (`cmd-shift-p` > "task: spawn" > "Review Claude Changes")
4. All files Claude edited open at the relevant lines
5. Use `alt-]` / `alt-[` to jump between diff hunks
6. Use `alt-\` to expand all diffs inline
7. Use the git panel to stage/revert changes
8. When done reviewing, run **"Clear Claude Change Manifest"** to reset
### Change Manifest
Changes accumulate per Claude Code session at `~/.claude/changes/<session-id>.json`. A symlink at `~/.claude/changes/latest.json` always points to the current session.
Format:
```json
{
"session_id": "abc123",
"started": "2026-02-14T10:30:00Z",
"changes": [
{"file": "/path/to/file.rs", "line": 42, "tool": "Edit", "timestamp": "..."},
{"file": "/path/to/new.rs", "line": 1, "tool": "Write", "timestamp": "..."}
]
}
```Related Skills
vvvv-editor-extensions
Helps create vvvv gamma editor extensions — .HDE.vl file naming, Command node registration with keyboard shortcuts, SkiaWindow/SkiaWindowTopMost window types, docking with WindowFactory, and API access to hovered/selected nodes via VL.Lang Session nodes. Use when building editor plugins, custom tooling windows, or automating editor workflows.
claude-md-editor
Edit and maintain CLAUDE.md and project documentation files. Use when modifying documentation, asking about best practices, or performing documentation maintenance tasks.
ckeditor-rules
Defines CKEditor is being used for text editing
coeditor
Build React applications with CopilotKit and LangGraph for AI-powered collaborative editing. Creates production-ready editor applications (text, document, or node-based) with real-time AI assistance, shared state management, and agentic workflows. Use this skill when users want to build intelligent editing interfaces with AI collaboration features.
AudioEditor
AI-powered audio/video editing — transcription, intelligent cut detection, automated editing with crossfades, and optional cloud polish. USE WHEN clean audio, edit audio, remove filler words, clean podcast, remove ums, fix audio, cut dead air, polish audio, clean recording, transcribe and edit.
ai-editor-rules
AI代码编辑器规则模板集合 - 为Cursor、Windsurf、Claude Code、Cline等AI编辑器提供项目规则配置。适用于需要配置AI编码助手规则的开发者,包含全栈Web、移动端、Vue3+SpringBoot等技术栈模板。
bgo
Automated Blender build-go workflow. Automatically builds, removes old version, installs, enables, and launches Blender with your extension/add-on. Use when you want to quickly test changes, execute complete build-to-launch cycle, or run custom packaging scripts with automatic Blender launch.
maintenance
Cleans up and organizes project files. Use when user mentions '整理', 'cleanup', 'アーカイブ', 'archive', '肥大化', 'Plans.md', 'session-log', or asks to clean up old tasks, archive completed items, or organize files. Do NOT load for: 実装作業, レビュー, 新機能開発, デプロイ.
hello-skill
每次对话开始时,声明"[Skills✏️已加载]"
zylvie-automation
Automate Zylvie tasks via Rube MCP (Composio). Always search tools first for current schemas.
zoominfo-automation
Automate Zoominfo tasks via Rube MCP (Composio). Always search tools first for current schemas.
zoho-invoice-automation
Automate Zoho Invoice tasks via Rube MCP (Composio): invoices, estimates, expenses, clients, and payment tracking. Always search tools first for current schemas.