Awesome-omni-skill 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.

install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/tools/zed-editor" ~/.claude/skills/diegosouzapw-awesome-omni-skill-zed-editor-7e1b3a && rm -rf "$T"
manifest: skills/tools/zed-editor/SKILL.md
source content

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

# 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

[
  {
    "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:

"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

"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:

"alt-w": ["workspace::SendKeystrokes", "cmd-c escape"]

Move down N lines:

"alt-down": ["workspace::SendKeystrokes", "down down down down"]

Select syntax node + copy + undo selection:

"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):

{
  "context": "vim_mode == normal && !menu",
  "bindings": {
    "shift-y": ["workspace::SendKeystrokes", "y $"]
  }
}

Vim insert mode escape via jk:

{
  "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

ActionDescription
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

ActionDescription
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

ActionDescription
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

ActionDescription
terminal_panel::ToggleFocus
Toggle/focus terminal
workspace::NewTerminal
New terminal tab

Git

ActionDescription
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:

{
  // 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

{
  "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

[
  {
    "label": "Run current file",
    "command": "python $ZED_FILE",
    "use_new_terminal": false,
    "allow_concurrent_runs": false,
    "reveal": "always"
  }
]

Available Environment Variables

VariableValue
$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

OptionValuesDefault
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 stringproject root
env
object of env vars
{}
tags
array of strings
[]

CLI Usage

# 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:

    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:

    "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:

    python3 -c "import json; json.load(open('$CONFIG_DIR/keymap.json'))" && echo "Valid JSON"
    

Workflow: Opening a Project in Zed

# 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:

[
  {
    "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:

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
:

{
  "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:

{
  "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": "..."}
  ]
}