Workspaces and Workspace Trust

Purpose and Scope

A VS Code workspace is the boundary that tells the workbench, extensions, terminals, source control providers, and AI features which folders belong to the current editing context. In the simplest case, that boundary is a single opened folder. In a multi-root workspace, several folders are open together and features must keep their state associated with the correct folder. Workspace Trust is the security layer over that boundary: when code is unfamiliar, VS Code can keep the window in Restricted Mode so automatic execution by the workbench and extensions is limited until the user grants trust.

This page explains the repository-level pieces that participate in that model for extension enablement and Copilot workspace-aware behavior. The core trust transition participant coordinates extension host behavior when the trust state changes. The Copilot files show how AI sessions discover whether they are running in an agent-session workspace, how chat sessions remember selected workspace folders, how repository changes are computed per folder, and how completions observe the VS Code workspace. Together, these sources show the practical consequence of the workspace boundary: state, permissions, repository context, and generated changes must all be scoped to the folder or window that the user has chosen.

Sources: src/vs/workbench/contrib/extensions/browser/extensionEnablementWorkspaceTrustTransitionParticipant.ts, extensions/copilot/src/extension/chatSessions/vscode-node/agentSessionsWorkspace.ts, extensions/copilot/src/extension/chatSessions/vscode-node/chatSessionWorkspaceFolderServiceImpl.ts

Relevant Source Files

  • src/vs/workbench/contrib/extensions/browser/extensionEnablementWorkspaceTrustTransitionParticipant.ts — Registers a workbench contribution that reacts to Workspace Trust transitions before the transition completes, updating extension enablement and restarting or reloading extension hosts when necessary.
  • extensions/copilot/src/extension/chatSessions/vscode-node/agentSessionsWorkspace.ts — Adapts the VS Code workspace API into Copilot's IAgentSessionsWorkspace service by exposing workspace.isAgentSessionsWorkspace.
  • extensions/copilot/src/extension/chatSessions/vscode-node/chatSessionWorkspaceFolderServiceImpl.ts — Tracks the workspace folder associated with each chat session, persists metadata, invalidates cache entries, and computes changed files for session worktrees in multi-root scenarios.
  • extensions/copilot/src/extension/chatSessions/vscode-node/claudeWorkspaceFolderServiceImpl.ts — Computes and caches repository changes for Claude-backed chat sessions using Git state, branch/base-branch inputs, and vscode.ChatSessionChangedFile objects.
  • extensions/copilot/src/extension/completions-core/vscode-node/extension/src/completionsObservableWorkspace.ts — Connects completions to the shared VSCodeWorkspace implementation through the ICompletionsObservableWorkspace service contract.
  • extensions/copilot/src/extension/completions-core/vscode-node/extension/src/codeReferencing/index.ts — Enables or disables public code reference tracking based on Copilot token capabilities, which affects how completions can surface code-reference behavior in the workspace context.

Workspace Trust Runtime Behavior

Workspace Trust is not just a UI prompt; it is a runtime state that changes how extension code is allowed to run. The transition participant is registered only when workspace trust is enabled and only after trust initialization completes. That sequencing matters because the source comments state that trust is initialized before the extension host starts, so the participant does not need to run during initial startup. Instead, it handles later state changes: when a user trusts a previously restricted workspace, it updates extension enablement; when a user moves from trusted to untrusted, it must make sure already-running extension code is brought into the new security boundary.

The implementation distinguishes local and remote extension host behavior. On a transition from trusted to untrusted with a remote authority, the host service reloads the window. Without a remote authority, the extension service stops extension hosts with the localized reason “Changing workspace trust,” the extension enablement service updates enablement according to the new trust state, and extension hosts are restarted if they were successfully stopped. This gives the workbench a concrete enforcement point: extensions affected by trust do not simply keep running with stale assumptions after the user restricts the workspace.

Sources: src/vs/workbench/contrib/extensions/browser/extensionEnablementWorkspaceTrustTransitionParticipant.ts

Single-Folder and Multi-Root Session Mapping

A single-folder workspace lets most services infer the active project from the window. Multi-root workspaces require more explicit mapping because a session, edit, Git repository, or AI operation may belong to one folder and not another. ChatSessionWorkspaceFolderService is the clearest source-backed example here. Its class comment states that it tracks workspace folder selections for chat sessions and that this is used in multi-root workspaces where some folders may not have Git repositories. The service keeps a session-to-folder entry, maps session IDs to repository keys, records sessions with no repository properties, and keeps a reverse association from folder URI to session IDs for cache invalidation.

Tracking starts by creating a WorkspaceFolderEntry with a folder path and timestamp, storing it under the session ID, and adding the session to the set associated with the folder URI. Deletion reverses that mapping: it invalidates the session cache, removes the session ID from the folder association, deletes the in-memory entry, and asks the metadata store to delete persisted session metadata. This is the kind of bookkeeping multi-root features need: once a chat session is tied to a folder, later refreshes and cleanups can operate on the correct folder without confusing neighboring roots in the same window.

Sources: extensions/copilot/src/extension/chatSessions/vscode-node/chatSessionWorkspaceFolderServiceImpl.ts

Agent and Copilot Workspace Context

Agent sessions have their own workspace-aware entry point. AgentSessionsWorkspace implements IAgentSessionsWorkspace and exposes a single property, isAgentSessionsWorkspace, which forwards to vscode.workspace.isAgentSessionsWorkspace. That small adapter is important because it gives Copilot services an injectable way to ask whether they are running in an agent-session workspace without coupling every consumer directly to the VS Code API. In docs terms, this supports the shared trust boundary between the normal VS Code window and the Agents window: agent behavior is still grounded in the workspace state exposed by VS Code.

Copilot completions also depend on a workspace abstraction. CompletionsObservableWorkspace extends VSCodeWorkspace and declares the ICompletionsObservableWorkspace service brand, which means completions can consume observable workspace behavior through a domain-specific service contract. Public code referencing is adjacent to this workspace context. The CodeReference class listens for Copilot token changes outside tests, sets an enabled flag from codeQuoteEnabled, disposes engagement-tracking subscriptions when public code references are disabled, and creates CodeRefEngagementTracker when they are enabled. The source does not make workspace trust decisions there, but it shows that AI workspace behavior is also gated by authentication and feature entitlements.

Sources: extensions/copilot/src/extension/chatSessions/vscode-node/agentSessionsWorkspace.ts, extensions/copilot/src/extension/completions-core/vscode-node/extension/src/completionsObservableWorkspace.ts, extensions/copilot/src/extension/completions-core/vscode-node/extension/src/codeReferencing/index.ts

Repository Changes and Chat Session Files

Workspace folder selection becomes especially visible when a chat or agent session needs to describe file changes. ClaudeWorkspaceFolderService computes repository changes for a current working directory, branch name, and base branch name. It builds a cache key from those three inputs, returns cached results unless forced to refresh, and deduplicates concurrent work with an in-flight promise map. The resulting changes are transformed into vscode.ChatSessionChangedFile objects that include the workspace file URI, an optional original Git URI, an optional modified file URI, and addition/deletion statistics.

The service also uses a well-known empty tree object constant, which is the Git object used when comparing against an empty repository state. Its Git-oriented inputs make the folder boundary explicit: repository changes are not computed for the abstract window; they are computed for a repository path. In multi-root workspaces, that prevents a session associated with one folder from accidentally reporting changes from another. The companion chat-session folder service adds another layer by tracking repository properties, session repository keys, and sessions that lack repository properties, which is necessary because not every workspace folder is necessarily a Git repository.

Sources: extensions/copilot/src/extension/chatSessions/vscode-node/claudeWorkspaceFolderServiceImpl.ts, extensions/copilot/src/extension/chatSessions/vscode-node/chatSessionWorkspaceFolderServiceImpl.ts

Compact Reference

ComponentPublic shape visible in sourceWorkspace responsibility
ExtensionEnablementWorkspaceTrustTransitionParticipantIWorkbenchContribution subclassRegisters an IWorkspaceTrustTransitionParticipant after trust initialization and updates extension enablement before trust transitions complete.
participate(trusted: boolean): Promise<void>Transition callbackFor trusted transitions, updates extension enablement; for untrusted transitions, reloads remote windows or stops, updates, and restarts local extension hosts.
AgentSessionsWorkspaceImplements IAgentSessionsWorkspaceExposes workspace.isAgentSessionsWorkspace through Copilot service injection.
ChatSessionWorkspaceFolderServiceImplements IChatSessionWorkspaceFolderServiceTracks session-to-folder state, persists metadata, associates sessions with folder URIs, and invalidates caches.
trackSessionWorkspaceFolder(sessionId, workspaceFolderUri, repositoryProperties?)Async methodRecords which workspace folder a chat session belongs to, including optional repository metadata.
deleteTrackedWorkspaceFolder(sessionId)Async methodRemoves persisted and in-memory folder tracking for a session.
ClaudeWorkspaceFolderService.getWorkspaceChanges(cwd, gitBranch, gitBaseBranch, forceRefresh?)Async methodReturns cached or freshly computed vscode.ChatSessionChangedFile entries for a repository path.
CompletionsObservableWorkspaceExtends VSCodeWorkspaceProvides the completions subsystem with an observable VS Code workspace service.
CodeReference.register() and onCopilotToken(...)Token-gated registrationEnables code reference engagement tracking only when Copilot token data allows code quotes.

Implementation Guidance

When changing workspace or trust-sensitive behavior, treat the workspace as a security and state boundary, not only as a list of folders. If the change affects extensions that may execute code, make sure it participates in the trust transition sequence early enough that the extension host cannot continue with stale enablement. If the change affects agent or chat sessions, make the selected folder explicit and preserve enough metadata to refresh, delete, and recompute state per session. Multi-root users should be able to reason about which folder an AI session or repository comparison is acting on.

For Copilot or agent features, prefer injectable service abstractions like IAgentSessionsWorkspace, IChatSessionWorkspaceFolderService, and ICompletionsObservableWorkspace over direct, scattered reads from global workspace state. That pattern makes the trust and workspace context easier to test and easier to reuse across normal editor windows and agent-session windows. Also distinguish between workspace trust, authentication entitlements, and repository state: trust controls whether workspace code can be executed freely, token flags such as codeQuoteEnabled control feature availability, and Git-derived workspace changes control what a chat session can report or review.

Sources: src/vs/workbench/contrib/extensions/browser/extensionEnablementWorkspaceTrustTransitionParticipant.ts, extensions/copilot/src/extension/chatSessions/vscode-node/agentSessionsWorkspace.ts, extensions/copilot/src/extension/chatSessions/vscode-node/chatSessionWorkspaceFolderServiceImpl.ts, extensions/copilot/src/extension/chatSessions/vscode-node/claudeWorkspaceFolderServiceImpl.ts, extensions/copilot/src/extension/completions-core/vscode-node/extension/src/completionsObservableWorkspace.ts, extensions/copilot/src/extension/completions-core/vscode-node/extension/src/codeReferencing/index.ts

Next Steps

To continue from this page, read the source-control and Copilot context pages together. Source control explains the Git repository concepts that chat sessions use when producing changed-file lists, while Copilot context explains how AI features gather and apply workspace information. For implementation work, start with the transition participant if your change affects restricted versus trusted execution, and start with the chat-session workspace-folder services if your change affects multi-root agent sessions or per-folder change reporting.