You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow up Zed upstream updates: untranslated MCP entries, unrecognized write/default permission keys, sandbox_permissions, global ignore, commands, Windows global path #2415
Seven Zed drifts, several of which make rulesync emit config Zed silently ignores: MCP servers are forwarded untranslated (a disabled server is emitted enabled), canonical write maps to a tool name Zed does not recognize, there is no way to set agent.tool_permissions.default, agent.sandbox_permissions is unauthorable, ignore has no global scope, commands are unsupported although Zed skills are the slash-command surface, and every global path is wrong on Windows.
Recent Releases
gh release list -R zed-industries/zed (stable channel), 2026-05 → 2026-07:
Version
Date
Relevant change
v1.4.2
2026-05-27
Skills shipped; Rules Library removed; global AGENTS.md added
--targets zed --features "*" --dry-run
→ .rules, .zed/settings.json (ignore + mcp + permissions)
→ commands / subagents / hooks / checks all "does not support the feature … Skipping."
--targets zed --features "*" --global --dry-run
→ .config/zed/AGENTS.md, .config/zed/settings.json (mcp + permissions), 41 skills
→ NO ignore file (global ignore unsupported)
Gaps
1. mcp — context_servers entries are forwarded untranslated
Upstream: Zed's context_servers value is a Rust #[serde(untagged)] enum (ContextServerSettingsContent in crates/settings_content/src/project.rs) with exactly three variants: Stdio (enabled: bool defaulting to true, remote: bool, flattened ContextServerCommand { command: PathBuf (serde-renamed from path), args, env, timeout }), Http (enabled, url, headers, timeout, oauth), and Extension (enabled, remote, settings). Docs: zed.dev/docs/ai/mcp.
rulesync: ZedMcp.fromRulesyncMcp (src/features/mcp/zed-mcp.ts) writes rulesyncMcp.getMcpServers() verbatim, and getMcpServers() strips only targets/description/exposed/envVars. So canonical fields reach Zed unchanged:
disabled: true → Zed has no disabled key; it reads enabled (default true). A server the user disabled in rulesync is emitted enabled in Zed.
httpUrl: "..." (no url) → matches no variant; not recognized as an HTTP server.
command: ["npx", "-y", "pkg"] (array form, allowed by the canonical schema) → Zed expects a single string path plus args.
type: "sse" → Zed has no SSE variant.
2. ignore — private_files has no global scope
Upstream: private_files is a worktree setting (WorktreeSettingsContent.private_files, crates/settings_content/src/project.rs; reference: all settings — "Private Files"). Zed layers default → user (~/.config/zed/settings.json) → project (.zed/settings.json), so the key is valid in the user settings file — which rulesync already writes for MCP and permissions in --global mode.
rulesync: project only. ZedIgnore.getSettablePaths() (src/features/ignore/zed-ignore.ts) takes no global option and hardcodes .zed/settings.json; the processor's global target list is ["kiro", "kiro-cli", "kiro-ide"]. The --global dry-run emits no ignore file.
Secondary, same adapter: the merge is additive-only — uniq([...existingPrivateFiles, ...patterns]) — so a pattern removed from .rulesync/.aiignore is never retracted from settings.json.
3. permissions — no way to set agent.tool_permissions.default
Upstream: Zed's per-tool default is only rung 5 of the precedence ladder; rung 6 is the global agent.tool_permissions.default ("confirm" default / "allow" / "deny"), documented at tool permissions ("Rule Precedence", "Global Auto-Approve") and MCP ("Tool Permissions" — it is the mechanism for MCP tools).
rulesync: ZedPermissions.fromRulesyncPermissions (src/features/permissions/zed-permissions.ts) only writes agent.tool_permissions.tools.<tool>; it spreads and preserves an existing top-level default but never sets it. The canonical all-tools key * is treated as an ordinary category and goes through toZedToolName("*") → tools["*"], which is not a Zed tool name and is silently ignored.
4. permissions — canonical write is not mapped to Zed's write_file
Upstream: Zed's permission-gated tool list (supported tools, matching docs/src/ai/tools.md) is terminal, edit_file, write_file, delete_path, move_path, copy_path, create_directory, fetch, search_web, skill.
rulesync: CANONICAL_TO_ZED_TOOL_NAMES (src/features/permissions/zed-permissions.ts) covers bash, read, edit, webfetch, websearch only. write is a documented canonical category (docs/reference/file-formats.md) and falls through the passthrough branch, so rulesync emits tools.write, which Zed does not recognize — the rule is silently inert. Same class of bug as the already-fixed web_search → search_web (Follow up Zed upstream updates: permissions web-search tool name should be search_web (not web_search) #1850).
5. permissions — agent.sandbox_permissions is not authorable
Upstream: Zed shipped OS-level agent sandboxing with a persisted settings surfaceagent.sandbox_permissions: network_hosts (exact host or leading-*. wildcard), allow_all_hosts, write_paths, allow_fs_write_all, allow_unsandboxed, warn_confusable_unicode (SandboxPermissionsContent, crates/settings_content/src/agent.rs). Docs: sandboxing ("Persistent Sandbox Permissions"), added 2026-06-23 (#59774), security review 2026-07-10 (#60291); prompt/network work landed in v1.8.2 (2026-06-24) and v1.10.0 (2026-07-08).
rulesync: writes only agent.tool_permissions into the same file. The tool-scoped zed override in .rulesync/permissions.json is the generic CanonicalPermissionsOverrideSchema (src/types/permissions.ts) — it carries only a permission block, so there is no slot for these keys. This is a different control plane from tool permissions (the Zed docs are explicit: tool permissions gate whether a call runs; the sandbox constrains what the running call can touch), so it cannot be expressed through the canonical allow/ask/deny model.
6. commands — unsupported, though Zed skills are the slash-command surface
Upstream: Zed exposes every installed skill as a /name slash command and as @skill (manual invocation), and disable-model-invocation: true makes a skill user-invocable only (disable-model-invocation). Zed's own Rules→Skills migration does exactly this: "Non-default Rules become global Skills in ~/.agents/skills/, each with disable-model-invocation: true. They remain user-invocable by slash command or @-mention." (migrating to skills, v1.4.2, 2026-05-27).
rulesync: unsupported — there is no zed-command.ts; the dry-run prints Target 'zed' does not support the feature 'commands'. Skipping.
Precedent: src/features/commands/devin-command.ts emits rulesync commands as SKILL.md files on Devin's native skills surface for exactly this reason, using commandSlug / command-skill-ownership.ts to keep the commands feature from colliding with the skills feature's ownership of the same tree.
7. rules / mcp / permissions — global scope uses the wrong path on Windows
Upstream: Zed's user config directory is %APPDATA%\Zed\ on Windows, not ~/.config/zed — ~/.config/zed/settings.json … Windows %APPDATA%\Zed\settings.json (configuring zed); and for the personal instructions file, "On Windows, the equivalent file is under %APPDATA%\Zed\AGENTS.md" (personal instructions, repeated in migrating to skills).
rulesync: ZED_GLOBAL_DIR = join(".config", "zed") (src/constants/zed-paths.ts) is unconditional, and every global adapter uses it (zed-rule.ts, zed-mcp.ts, zed-permissions.ts). On Windows, --global writes to %USERPROFILE%\.config\zed\, which Zed never reads. Precedent for platform-branching a global dir already exists in src/constants/warp-paths.ts (WARP_LINUX_DIR vs WARP_WIN32_DIR).
Proposed Follow-up
Translate in ZedMcp.fromRulesyncMcp — disabled → enabled: !disabled, httpUrl → url, array command → string command + prepended args — and drop canonical-only keys Zed cannot read (type, transport, alwaysAllow, tools, kiro*, enabledTools/disabledTools, trust, networkTimeout, cwd). Warn (or skip) on type: "sse". Mirror the inverse in toRulesyncMcp().
Add global to ZedIgnore.getSettablePaths() (→ ZED_GLOBAL_DIR), register zed in ignoreProcessorGlobalToolTargets, and track rulesync-managed patterns so removals propagate (or at least warn on drop, matching the Kilo/Augment convention).
Map the canonical * category's catch-all rule onto agent.tool_permissions.default instead of emitting a tools["*"] entry, and round-trip it in toRulesyncPermissions().
Add write: "write_file" to CANONICAL_TO_ZED_TOOL_NAMES and its inverse. grep already matches Zed's tool name; glob has no permission-gated Zed counterpart (find_path is not in the gated list), so leaving it as passthrough is correct.
Give zed a dedicated permissions override schema (precedent: KimiCodePermissionsOverrideSchema, ClinePermissionsOverrideSchema, HermesPermissionsOverrideSchema in src/types/permissions.ts) carrying sandbox_permissions, merged non-destructively under agent in settings.json for both scopes, and re-extracted on import.
Add ZedCommand emitting .agents/skills/<slug>/SKILL.md (project) and ~/.agents/skills/<slug>/SKILL.md (global) with { name, description, disable-model-invocation: true }, reusing the Devin ownership/slug helpers, plus the Tool × Feature happy-path e2e case.
Branch ZED_GLOBAL_DIR on process.platform === "win32" → AppData/Roaming/Zed, following the warp-paths pattern. (Zed skills at ~/.agents/skills/ are home-relative on every platform and are unaffected.)
Non-gaps / inconclusive
subagents — re-verified against agent profiles (current main): an agent.profiles.<id> entry carries only name, tools, enable_all_context_servers, context_servers, default_model. There is still no instructions/system-prompt field, so a rulesync subagent's body would be dropped. The spawn_agent tool (parallel agents) is a runtime affordance with no persisted per-agent definition file. The decision recorded in Follow up Zed upstream updates: subagents via Agent Profiles (agent.profiles in settings.json) #2033 still holds — no gap.
hooks — Zed does have a hooks field, but on task templates in tasks.json (tasks#hooks). The only supported event is create_worktree (fires after Zed creates a linked Git worktree, with ZED_WORKTREE_ROOT / ZED_MAIN_GIT_WORKTREE). It is an editor/Git event, not an agent-lifecycle event; none of rulesync's canonical HOOK_EVENTS maps onto it. Not a material gap unless the maintainer wants a Zed-only event.
checks — rulesync checks are code-review specs consumed only by Amp and Hermes. Zed has no equivalent surface.
rules — Zed v1.4.2 deprecated the Rules Library, but both file surfaces rulesync targets are still documented and current: project .rules (first entry in the compatibility precedence list, project instructions) and personal ~/.config/zed/AGENTS.md. Aside from the Windows path (gap 7), no change needed.
skills — frontmatter is still exactly name / description / disable-model-invocation (frontmatter fields); Zed says it "plans to include other fields promoted by the Agent Skills specification in the near future" — unconfirmed which, so nothing to follow yet. Paths match ZED_SKILLS_DIR_PATH. Minor, non-capability: Zed rejects skill names that are not [a-z0-9-], ≤64 chars, no leading/trailing or doubled hyphen; ZedSkillFrontmatterSchema accepts any string, so an invalid name generates a skill Zed silently fails to load.
Summary
Seven Zed drifts, several of which make rulesync emit config Zed silently ignores: MCP servers are forwarded untranslated (a
disabledserver is emitted enabled), canonicalwritemaps to a tool name Zed does not recognize, there is no way to setagent.tool_permissions.default,agent.sandbox_permissionsis unauthorable, ignore has no global scope, commands are unsupported although Zed skills are the slash-command surface, and every global path is wrong on Windows.Recent Releases
gh release list -R zed-industries/zed(stable channel), 2026-05 → 2026-07:AGENTS.mdaddedskilltool wired into the Tool Permissions settings UIDocs commits:
docs/src/ai/instructions.mdadded 2026-06-04 (#57614, AI docs restructure);docs/src/ai/sandboxing.mdadded 2026-06-23 (#59774), security review 2026-07-10 (#60291).Dry-run baseline:
Gaps
1. mcp —
context_serversentries are forwarded untranslatedcontext_serversvalue is a Rust#[serde(untagged)]enum (ContextServerSettingsContentincrates/settings_content/src/project.rs) with exactly three variants:Stdio(enabled: booldefaulting totrue,remote: bool, flattenedContextServerCommand { command: PathBuf (serde-renamed from path), args, env, timeout }),Http(enabled,url,headers,timeout,oauth), andExtension(enabled,remote,settings). Docs: zed.dev/docs/ai/mcp.ZedMcp.fromRulesyncMcp(src/features/mcp/zed-mcp.ts) writesrulesyncMcp.getMcpServers()verbatim, andgetMcpServers()strips onlytargets/description/exposed/envVars. So canonical fields reach Zed unchanged:disabled: true→ Zed has nodisabledkey; it readsenabled(defaulttrue). A server the user disabled in rulesync is emitted enabled in Zed.httpUrl: "..."(nourl) → matches no variant; not recognized as an HTTP server.command: ["npx", "-y", "pkg"](array form, allowed by the canonical schema) → Zed expects a single string path plusargs.type: "sse"→ Zed has no SSE variant.2. ignore —
private_fileshas no global scopeprivate_filesis a worktree setting (WorktreeSettingsContent.private_files,crates/settings_content/src/project.rs; reference: all settings — "Private Files"). Zed layers default → user (~/.config/zed/settings.json) → project (.zed/settings.json), so the key is valid in the user settings file — which rulesync already writes for MCP and permissions in--globalmode.projectonly.ZedIgnore.getSettablePaths()(src/features/ignore/zed-ignore.ts) takes noglobaloption and hardcodes.zed/settings.json; the processor's global target list is["kiro", "kiro-cli", "kiro-ide"]. The--globaldry-run emits no ignore file.uniq([...existingPrivateFiles, ...patterns])— so a pattern removed from.rulesync/.aiignoreis never retracted fromsettings.json.3. permissions — no way to set
agent.tool_permissions.defaultdefaultis only rung 5 of the precedence ladder; rung 6 is the globalagent.tool_permissions.default("confirm"default /"allow"/"deny"), documented at tool permissions ("Rule Precedence", "Global Auto-Approve") and MCP ("Tool Permissions" — it is the mechanism for MCP tools).ZedPermissions.fromRulesyncPermissions(src/features/permissions/zed-permissions.ts) only writesagent.tool_permissions.tools.<tool>; it spreads and preserves an existing top-leveldefaultbut never sets it. The canonical all-tools key*is treated as an ordinary category and goes throughtoZedToolName("*")→tools["*"], which is not a Zed tool name and is silently ignored.4. permissions — canonical
writeis not mapped to Zed'swrite_filedocs/src/ai/tools.md) isterminal,edit_file,write_file,delete_path,move_path,copy_path,create_directory,fetch,search_web,skill.CANONICAL_TO_ZED_TOOL_NAMES(src/features/permissions/zed-permissions.ts) coversbash,read,edit,webfetch,websearchonly.writeis a documented canonical category (docs/reference/file-formats.md) and falls through the passthrough branch, so rulesync emitstools.write, which Zed does not recognize — the rule is silently inert. Same class of bug as the already-fixedweb_search→search_web(Follow up Zed upstream updates: permissions web-search tool name should be search_web (not web_search) #1850).5. permissions —
agent.sandbox_permissionsis not authorableagent.sandbox_permissions:network_hosts(exact host or leading-*.wildcard),allow_all_hosts,write_paths,allow_fs_write_all,allow_unsandboxed,warn_confusable_unicode(SandboxPermissionsContent,crates/settings_content/src/agent.rs). Docs: sandboxing ("Persistent Sandbox Permissions"), added 2026-06-23 (#59774), security review 2026-07-10 (#60291); prompt/network work landed in v1.8.2 (2026-06-24) and v1.10.0 (2026-07-08).agent.tool_permissionsinto the same file. The tool-scopedzedoverride in.rulesync/permissions.jsonis the genericCanonicalPermissionsOverrideSchema(src/types/permissions.ts) — it carries only apermissionblock, so there is no slot for these keys. This is a different control plane from tool permissions (the Zed docs are explicit: tool permissions gate whether a call runs; the sandbox constrains what the running call can touch), so it cannot be expressed through the canonical allow/ask/deny model.6. commands — unsupported, though Zed skills are the slash-command surface
/nameslash command and as@skill(manual invocation), anddisable-model-invocation: truemakes a skill user-invocable only (disable-model-invocation). Zed's own Rules→Skills migration does exactly this: "Non-default Rules become global Skills in~/.agents/skills/, each withdisable-model-invocation: true. They remain user-invocable by slash command or@-mention." (migrating to skills, v1.4.2, 2026-05-27).unsupported— there is nozed-command.ts; the dry-run printsTarget 'zed' does not support the feature 'commands'. Skipping.src/features/commands/devin-command.tsemits rulesync commands asSKILL.mdfiles on Devin's native skills surface for exactly this reason, usingcommandSlug/command-skill-ownership.tsto keep the commands feature from colliding with the skills feature's ownership of the same tree.7. rules / mcp / permissions — global scope uses the wrong path on Windows
%APPDATA%\Zed\on Windows, not~/.config/zed—~/.config/zed/settings.json… Windows%APPDATA%\Zed\settings.json(configuring zed); and for the personal instructions file, "On Windows, the equivalent file is under%APPDATA%\Zed\AGENTS.md" (personal instructions, repeated in migrating to skills).ZED_GLOBAL_DIR = join(".config", "zed")(src/constants/zed-paths.ts) is unconditional, and every global adapter uses it (zed-rule.ts,zed-mcp.ts,zed-permissions.ts). On Windows,--globalwrites to%USERPROFILE%\.config\zed\, which Zed never reads. Precedent for platform-branching a global dir already exists insrc/constants/warp-paths.ts(WARP_LINUX_DIRvsWARP_WIN32_DIR).Proposed Follow-up
ZedMcp.fromRulesyncMcp—disabled→enabled: !disabled,httpUrl→url, arraycommand→ stringcommand+ prependedargs— and drop canonical-only keys Zed cannot read (type,transport,alwaysAllow,tools,kiro*,enabledTools/disabledTools,trust,networkTimeout,cwd). Warn (or skip) ontype: "sse". Mirror the inverse intoRulesyncMcp().globaltoZedIgnore.getSettablePaths()(→ZED_GLOBAL_DIR), registerzedinignoreProcessorGlobalToolTargets, and track rulesync-managed patterns so removals propagate (or at least warn on drop, matching the Kilo/Augment convention).*category's catch-all rule ontoagent.tool_permissions.defaultinstead of emitting atools["*"]entry, and round-trip it intoRulesyncPermissions().write: "write_file"toCANONICAL_TO_ZED_TOOL_NAMESand its inverse.grepalready matches Zed's tool name;globhas no permission-gated Zed counterpart (find_pathis not in the gated list), so leaving it as passthrough is correct.zeda dedicated permissions override schema (precedent:KimiCodePermissionsOverrideSchema,ClinePermissionsOverrideSchema,HermesPermissionsOverrideSchemainsrc/types/permissions.ts) carryingsandbox_permissions, merged non-destructively underagentinsettings.jsonfor both scopes, and re-extracted on import.ZedCommandemitting.agents/skills/<slug>/SKILL.md(project) and~/.agents/skills/<slug>/SKILL.md(global) with{ name, description, disable-model-invocation: true }, reusing the Devin ownership/slug helpers, plus the Tool × Feature happy-path e2e case.ZED_GLOBAL_DIRonprocess.platform === "win32"→AppData/Roaming/Zed, following the warp-paths pattern. (Zed skills at~/.agents/skills/are home-relative on every platform and are unaffected.)Non-gaps / inconclusive
agent.profiles.<id>entry carries onlyname,tools,enable_all_context_servers,context_servers,default_model. There is still no instructions/system-prompt field, so a rulesync subagent's body would be dropped. Thespawn_agenttool (parallel agents) is a runtime affordance with no persisted per-agent definition file. The decision recorded in Follow up Zed upstream updates: subagents via Agent Profiles (agent.profiles in settings.json) #2033 still holds — no gap.hooksfield, but on task templates intasks.json(tasks#hooks). The only supported event iscreate_worktree(fires after Zed creates a linked Git worktree, withZED_WORKTREE_ROOT/ZED_MAIN_GIT_WORKTREE). It is an editor/Git event, not an agent-lifecycle event; none of rulesync's canonicalHOOK_EVENTSmaps onto it. Not a material gap unless the maintainer wants a Zed-only event.checksare code-review specs consumed only by Amp and Hermes. Zed has no equivalent surface..rules(first entry in the compatibility precedence list, project instructions) and personal~/.config/zed/AGENTS.md. Aside from the Windows path (gap 7), no change needed.name/description/disable-model-invocation(frontmatter fields); Zed says it "plans to include other fields promoted by the Agent Skills specification in the near future" — unconfirmed which, so nothing to follow yet. Paths matchZED_SKILLS_DIR_PATH. Minor, non-capability: Zed rejects skill names that are not[a-z0-9-], ≤64 chars, no leading/trailing or doubled hyphen;ZedSkillFrontmatterSchemaaccepts any string, so an invalid name generates a skill Zed silently fails to load.References
context_serversvariants and the Tool Permissions note (gaps 1, 3).private_filesas a worktree setting valid in user settings (gap 2).agent.sandbox_permissionssurface (gap 5).@invocation,disable-model-invocation, and the frontmatter field list (gap 6).%APPDATA%\Zed\user config dir (gap 7).create_worktreetask hook, checked and excluded.