Skip to content

Follow up Zed upstream updates: untranslated MCP entries, unrecognized write/default permission keys, sandbox_permissions, global ignore, commands, Windows global path #2415

Description

@dyoshikawa

Summary

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
v1.5.3 2026-06-03 Skill Creator; deprecated-Rules fixes
v1.7.2 / v1.8.2 2026-06-17 / 2026-06-24 Agent sandboxing prompts + network permission handling
v1.9.0 2026-07-01 skill tool wired into the Tool Permissions settings UI
v1.10.0 2026-07-08 Windows agent sandboxing protects Git metadata
v1.12.0 2026-07-23 Skill deletion UX (latest stable)

Docs commits: docs/src/ai/instructions.md added 2026-06-04 (#57614, AI docs restructure); docs/src/ai/sandboxing.md added 2026-06-23 (#59774), security review 2026-07-10 (#60291).

Dry-run baseline:

--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_searchsearch_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 surface agent.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

  1. Translate in ZedMcp.fromRulesyncMcpdisabledenabled: !disabled, httpUrlurl, 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().
  2. 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).
  3. 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().
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  • Follow up Zed upstream updates: subagents via Agent Profiles (agent.profiles in settings.json) #2033's last comment (2026-07-23) already noted three of these gaps (ignore global scope, MCP field translation, commands-as-skills) in passing, but the issue was closed on the subagents question only; nothing was filed or implemented for them, and all three were re-verified as present on 2026-07-26.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    consideringenhancementNew feature or requestmaintainer-scrapRough notes for AI implementation. Not for human eyes.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions