Skip to content

Workspace Trust

Wayland Core reads project config from .wayland-core.toml in your working directory. From v0.12.26, the keys in that file that can expand what the engine is allowed to do are honoured only in a trusted workspace. In an untrusted one they are stripped before the config is applied.

The reason is direct: cloning a repository should not be able to grant that repository an MCP server, a provider, or a hook that runs on your machine.

In an untrusted workspace, these tables and keys are removed from project config before it is applied:

KeyWhy it is authority-expanding
[profiles.*]Selects providers, models, and their settings
[mcp.servers.*]Declares external tool servers the engine will connect to
[providers.*]Declares provider endpoints and how they are reached
HooksRun commands at engine lifecycle points
env_passthroughDecides which environment variables reach subprocesses
Sandbox keysGovern shell containment

Everything else in project config is applied normally. A workspace you have not trusted is still fully usable; it simply cannot widen the engine’s authority on its own say-so.

Trust a workspace once:

Terminal window
wayland-core --trust-workspace

The grant is recorded against the workspace’s executable surface, not against its path. That distinction is the whole point: a path is a name, and a name can come to point at different content.

Before v0.13.0, an untrusted workspace failed in a way that was almost impossible to diagnose. Running --profile p reported:

Profile 'p' not found in config

for a profile that was plainly present in a file Core had just parsed and then discarded on the trust decision. The only true account of what happened was a tracing::warn! invisible at default verbosity.

From v0.13.0 the refusal names the trust decision and the remedy instead. A profile that genuinely was never written still reads as absent, so the clearer message cannot send you chasing --trust-workspace over a typo.

A workspace whose executable surface contains symlinks is trustable. The fingerprint follows each link and hashes the bytes it resolves to.

This matters for hosts that compose a workspace out of their own assets. Wayland Desktop links builtin and user skill directories into a per-chat workspace, and that workspace can obtain trust.

The property that makes this safe is what happens on change:

  • Rewriting a link’s target voids the grant.
  • Repointing a link at different content voids the grant.

Trust cannot outlive a change to what actually executes.

Dangling links, link cycles, and links pointing at devices or FIFOs still fail closed.

Two neighbouring rules landed in the same release and are worth knowing together with this one:

  • Project config can no longer raise max_tokens or max_turns. An untrusted repository cannot widen limits you set. Raise them in your own config instead.
  • A project [memory] block cannot defeat a global memory opt-out. Cloning a repository can no longer silently re-enable memory recording.

The egress master switch is operator-owned for the same reason: a project cannot negotiate it.

There is a second change in v0.12.26 that affects hosts rather than config authors. A runtime MCP server added over the json-stream protocol is now bound to the assistant identity that declared it, and a session with no identity to bind to refuses the declaration:

active assistant identity is required for a runtime MCP declaration

Supply an identity at spawn with --assistant NAME, or WAYLAND_ASSISTANT=NAME in the environment. Any stable name works; it is the same identity only_for_assistant matches against in config. It is not --agent, which selects a persona and a system prompt.

The refusal is announced on an error frame and an mcp_failed frame naming the server and the reason, and neither is fatal. The engine goes on to serve the session normally, so a host that does not render mcp_failed shows a conversation with no MCP tools and no visible cause. If you host the engine, render mcp_failed.

See Driving the Engine from a Host and MCP Client.