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.
git clone https://github.com/diegosouzapw/awesome-omni-skill
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"
skills/tools/zed-editor/SKILL.mdZed 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
- Detect OS to resolve config paths
- Read existing config before making any changes (preserve user's work)
- Validate JSON — all Zed configs are JSON arrays or objects; malformed JSON will silently break the editor config
- Write changes using careful JSON merging — don't clobber existing bindings/settings
- 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
,shiftfn - Special keys:
,up
,down
,left
,right
,enter
,escape
,tab
,space
,backspace
,delete
,home
,end
,pageuppagedown - Letters/numbers:
-a
,z
-09 - Multi-key sequences:
(space-separated, typed in sequence)"g e"
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:
— any editor paneEditor
— terminal panelTerminal
— file treeProjectPanel
— any dock panelDock
/vim_mode == normal
/insert
— vim mode statesvisual
— normal + visual modes combinedVimControl
— autocomplete/palette is openmenu
— no file openEmptyPane
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
- First identify the individual actions needed (use
or the All Actions reference)zed: open default keymap - Find the existing keybindings for each action
- Chain those key combos in a single SendKeystrokes string
- Test that none of the intermediate actions are async
Common Actions Reference
Editor Actions
| Action | Description |
|---|---|
| Copy selection |
| Cut selection |
| Paste |
| Undo |
| Redo |
| Select all |
| Format document |
| Toggle line comments |
| Move current line up |
| Move current line down |
| Duplicate line |
| Expand selection to syntax |
| Shrink selection |
| Go to definition |
| Go to declaration |
| Go to implementation |
| Rename symbol |
| Show code actions |
| Insert newline |
| Insert tab/indent |
| Outdent |
| Fold all |
| Unfold all |
Workspace Actions
| Action | Description |
|---|---|
| New file |
| Save |
| Save all |
| Open file dialog |
| Toggle left dock |
| Toggle right dock |
| Toggle bottom dock |
| Focus next pane |
| Focus previous pane |
| Chain keystrokes |
Navigation
| Action | Description |
|---|---|
| Open file finder |
| Open symbol search |
| Find in file |
| Find in project |
| Open outline view |
| Go to line number |
| Switch tabs |
| Open diagnostics |
Terminal
| Action | Description |
|---|---|
| Toggle/focus terminal |
| New terminal tab |
Git
| Action | Description |
|---|---|
| Toggle/focus git panel |
| Open project diff view |
| Open all modified files |
| Stage current hunk, advance to next |
| Unstage current hunk, advance to next |
| Toggle staged state |
| Commit staged changes |
| AI-generated commit message |
| Fetch from remote |
| Push to remote |
| Pull from remote |
| Restore/undo changes |
| Navigate to next diff hunk |
| Navigate to previous diff hunk |
| Expand all hunks inline |
| 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
| Variable | Value |
|---|---|
| Absolute path of current file |
| Filename only |
| Directory of current file |
| File path relative to project root |
| Directory relative to project root |
| Filename without extension |
| Current cursor row |
| Current cursor column |
| Currently selected text |
| Project root directory |
Task Options
| Option | Values | Default |
|---|---|---|
| / | |
| / | |
| , , | |
| , , | |
| path string | project root |
| object of env vars | |
| 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:
-
Read the current keymap:
cat "$CONFIG_DIR/keymap.json" 2>/dev/null || echo "[]" -
Parse the JSON and check for conflicting bindings on the same key in the same context.
-
Determine the action(s) needed. If a single action suffices, bind directly:
"cmd-shift-d": "editor::DuplicateLineDown" -
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
-
Add the binding to the appropriate context block (or create a new one).
-
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
- Create
in the project root.zed/tasks.json - Define tasks that use Zed environment variables
- 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 —
andkeymap.json
are arraystasks.json
.[]
is an objectsettings.json
.{} - 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.
is set atvim_mode
level, soEditor
will never match."Workspace && vim_mode == normal" - 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
- A PostToolUse hook in Claude Code records every file edit to a session manifest
- A Zed task reads the manifest and opens all changed files at the right lines
- 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
- Run Claude Code in your terminal -- it edits files as usual
- Switch to Zed
- Run the "Review Claude Changes" task from the command palette (
> "task: spawn" > "Review Claude Changes")cmd-shift-p - All files Claude edited open at the relevant lines
- Use
/alt-]
to jump between diff hunksalt-[ - Use
to expand all diffs inlinealt-\ - Use the git panel to stage/revert changes
- 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": "..."} ] }