Summary
Vibe v2.24.0 (2026-08-05) changed the config model: user and project config.toml layers now compose per-key instead of the project file replacing the user file. rulesync's Vibe adapters still model the two scopes as mutually exclusive and emit a warning whose claim is now false.
Recent Releases
Confirmed in source at v2.24.0: vibe/core/config/default_orchestrator.py:65-76 installs both TOML layers together (DefaultConfigLayer, GrowthbookLayer, user_layer, project_layer, EnvironmentLayer, override_layer, AdminConfigLayer); in v2.23.3 the same function selected exactly one TOML layer, so rulesync's model was correct through v2.23.3.
Gaps
1. mcp + permissions — the "exactly one config.toml" warning is now wrong and actively misleading
- Upstream: composition is per-key via merge strategies in
vibe/core/config/vibe_schema.py:290-330: mcp_servers union-merges by name, tools deep-merges, disabled_tools concatenates, enabled_tools replaces. Concretely: a global MCP server now survives into every project; global per-tool allowlist/denylist deep-merge underneath project values; deleting a server from project config no longer removes it if the user config declares one with the same name.
- rulesync:
warnIfGlobalVibeConfigIsShadowed (src/features/shared/vibe-config-scope.ts, called from vibe-mcp.ts:134 and vibe-permissions.ts:125) emits on any --global run in a project with .vibe/config.toml: "Vibe reads exactly one config.toml … the global file written by --global is ignored here." That claim is false as of v2.24.0 and steers users away from a global config that now takes effect. The same premise is documented in docs/reference/file-formats.md:1413, and the MCP removal-semantics note at :1040 needs revisiting (project-scope deletion is now shadowed by same-named user-scope servers).
- Follow-up: replace the warning with per-key-layering guidance (or drop it for Vibe ≥ 2.24.0), and update both doc locations.
2. Minor — the shadow check only inspects process.cwd()
Upstream discovery walks parent directories (_discover_config_file() in vibe/core/config/layers/project.py iterates [root, *root.parents]). Largely moot if gap 1 is resolved by removing the warning; otherwise walk parents to match.
Doc note (no code change possible)
v2.24.0 also adds an AdminConfigLayer fetched from https://<vibe_base_url>/api/v1/code/managed-config at the highest priority — server-delivered org policy that can silently override any rulesync-written key. Worth one sentence in the Vibe section of docs/reference/file-formats.md for users debugging an unapplied setting.
Verified in parity
Hooks (post_agent/pre_tool/post_tool unchanged since the v2.21.0 rename handled in #2423/#2441), permission field surface (permission/allowlist/denylist/sensitive_patterns), builtin tool names (still no glob), subagents, skills discovery roots, ignore, and commands (still no user-authored command surface upstream).
References
Summary
Vibe v2.24.0 (2026-08-05) changed the config model: user and project
config.tomllayers now compose per-key instead of the project file replacing the user file. rulesync's Vibe adapters still model the two scopes as mutually exclusive and emit a warning whose claim is now false.Recent Releases
Confirmed in source at v2.24.0:
vibe/core/config/default_orchestrator.py:65-76installs both TOML layers together (DefaultConfigLayer, GrowthbookLayer, user_layer, project_layer, EnvironmentLayer, override_layer, AdminConfigLayer); in v2.23.3 the same function selected exactly one TOML layer, so rulesync's model was correct through v2.23.3.Gaps
1. mcp + permissions — the "exactly one config.toml" warning is now wrong and actively misleading
vibe/core/config/vibe_schema.py:290-330:mcp_serversunion-merges byname,toolsdeep-merges,disabled_toolsconcatenates,enabled_toolsreplaces. Concretely: a global MCP server now survives into every project; global per-toolallowlist/denylistdeep-merge underneath project values; deleting a server from project config no longer removes it if the user config declares one with the same name.warnIfGlobalVibeConfigIsShadowed(src/features/shared/vibe-config-scope.ts, called fromvibe-mcp.ts:134andvibe-permissions.ts:125) emits on any--globalrun in a project with.vibe/config.toml: "Vibe reads exactly one config.toml … the global file written by --global is ignored here." That claim is false as of v2.24.0 and steers users away from a global config that now takes effect. The same premise is documented indocs/reference/file-formats.md:1413, and the MCP removal-semantics note at:1040needs revisiting (project-scope deletion is now shadowed by same-named user-scope servers).2. Minor — the shadow check only inspects
process.cwd()Upstream discovery walks parent directories (
_discover_config_file()invibe/core/config/layers/project.pyiterates[root, *root.parents]). Largely moot if gap 1 is resolved by removing the warning; otherwise walk parents to match.Doc note (no code change possible)
v2.24.0 also adds an
AdminConfigLayerfetched fromhttps://<vibe_base_url>/api/v1/code/managed-configat the highest priority — server-delivered org policy that can silently override any rulesync-written key. Worth one sentence in the Vibe section ofdocs/reference/file-formats.mdfor users debugging an unapplied setting.Verified in parity
Hooks (
post_agent/pre_tool/post_toolunchanged since the v2.21.0 rename handled in #2423/#2441), permission field surface (permission/allowlist/denylist/sensitive_patterns), builtin tool names (still noglob), subagents, skills discovery roots, ignore, and commands (still no user-authored command surface upstream).References
vibe/core/config/default_orchestrator.py(v2.24.0 vs v2.23.3) — layer list changevibe/core/config/vibe_schema.py:290-330— per-key merge strategies