What VS Code Remembers on Your Mac
VS Code stores configuration, extension state, workspace state, local file history, plugins, and logs across several locations on macOS. This post maps those directories, explains what they reveal, and separates local editor state from GitHub Copilot CLI and cloud data.

While doing a stock take of the ever-growing number of agent skills installed on my PC, I stumbled on a folder ~/Library/Application Support/Code/User expecting a settings file. Instead, I found databases, hashed workspace directories, file history, extension state, and traces of tools I had used.
It felt like finding a second workspace behind the workspace, one holding the editor’s memory of working with my code.
The tempting conclusion is that VS Code records everything you do. What I found instead is a modern editor keeping several kinds of memory, and they do not all live in the same place.
Editor state deserves the same care as your source code.
1. macOS Separates the Application From Its Memory#
On macOS, Visual Studio Code itself normally lives here:
/Applications/Visual Studio Code.app
That application bundle contains the program you launch. The preferences, databases, workspace state, and recovery files VS Code writes as you work live elsewhere:
~/Library/Application Support/Code/
This is the first useful distinction. /Applications contains the application. Application Support contains data that helps the application continue where it left off.
Command-line tools often follow a different Unix convention. That is why GitHub Copilot CLI uses ~/.copilot, while ordinary VS Code extensions are installed under ~/.vscode/extensions.
None of these paths is universal. VS Code Insiders uses Code - Insiders, portable mode changes the layout, and command-line flags can relocate both user data and extensions. But the default model is straightforward:
Visual Studio Code.app
|
+-- configuration and state
| `-- ~/Library/Application Support/Code/
|
+-- ordinary extension packages
| `-- ~/.vscode/extensions/
|
`-- project files
`-- wherever you cloned the repository
GitHub Copilot CLI
`-- ~/.copilot/
Installed code, application state, and project files are different things. Mixing them together makes the filesystem look more mysterious than it is.
2. macOS Has More Than One Library#
The tilde in ~/Library is doing important work. It means “the current user’s home directory.” Remove it and you are looking at a different storage domain.
~/Library/ resources and state for one user
/Library/ resources shared by every user on this Mac
/System/Library/ operating-system resources owned by Apple
Apple calls these the user, local, and system domains. Many familiar subdirectories can exist in more than one domain, but their scope changes:
| Location | Scope | Typical contents |
|---|---|---|
~/Library/Application Support | Current user | Per-user app state, databases and downloaded resources |
/Library/Application Support | All users | Machine-wide support files, shared templates and vendor resources |
~/Library/Preferences | Current user | Per-user preferences |
/Library/Preferences | All users | Machine-wide preferences and managed configuration |
~/Library/LaunchAgents | Current user | Background agents launched for that user |
/Library/LaunchAgents | All users | Vendor agents available across accounts |
/Library/LaunchDaemons | Whole machine | System-level background services, often running without a logged-in user |
/System/Library | Operating system | Apple frameworks, services and system resources |
This is why some installers prompt for an administrator password. Writing into /Library changes the machine for every account. Writing into ~/Library changes it for yours only.
VS Code Stable keeps the state discussed in this post under your personal ~/Library/Application Support/Code. A machine-wide installer, device-management product, shared runtime, launch daemon, or security agent may use /Library, but that is a separate scope.
/System/Library belongs to macOS, and unfamiliar files in /Library may support software used by every account on the Mac. Neither is a place to tidy up.
Sandboxed applications add one more variation. Their private Library can live inside a container such as ~/Library/Containers/<bundle-id>/Data/Library. The lesson is scope, not memorizing every path.
3. The User Directory Is More Than Preferences#
Inside ~/Library/Application Support/Code, the User directory is the centre of the story. This portable path:
~/Library/Application Support/Code/User
resolves to the same directory as a concrete home-directory path, which on my machine is:
/Users/ndamulelonemakhavhani/Library/Application Support/Code/User
The first form works on any Mac regardless of username; the second is the actual directory I inspected.
Its top level holds seven child directories and four files:
User/
├── agent-sessions.code-workspace
├── chatLanguageModels.json
├── globalStorage/
├── History/
├── mcp/
├── mcp.json
├── profiles/
├── settings.json
├── snippets/
├── sync/
└── workspaceStorage/
That list is a snapshot, not a schema. VS Code creates some entries only after the corresponding feature is used, extensions can add state, and future versions can change implementation details.
| Entry | Precise role |
|---|---|
settings.json | User-scoped VS Code settings written as JSON with comments |
chatLanguageModels.json | User configuration for additional or bring-your-own chat model providers and models |
mcp.json | User-profile configuration for MCP servers and reusable configuration inputs |
agent-sessions.code-workspace | A VS Code workspace descriptor containing folder references; the filename indicates agent-session use, though the file is application-managed |
globalStorage/ | Cross-workspace state persisted by VS Code and extensions |
workspaceStorage/ | State scoped to particular folders or workspaces |
History/ | Local History snapshots created from saved files, subject to VS Code’s limits and exclusions |
profiles/ | Data belonging to VS Code profiles, including the built-in default profile |
snippets/ | User-authored reusable code snippets |
sync/ | Local copies of the settings, keybindings, snippets, prompts, and extensions that Settings Sync uploads |
mcp/ | Supporting material managed by VS Code or MCP integrations |
Three of those entries are easy to misread. mcp/ holds supporting material that MCP integrations need, while mcp.json holds the declarative server definitions themselves. agent-sessions.code-workspace is a JSON workspace descriptor listing folder references. chatLanguageModels.json configures model connections, and API keys reach it through ${input:...} variables backed by secret storage instead of being pasted into the file.
settings.json, chatLanguageModels.json, mcp.json, and snippets are intended to be edited through VS Code or, when appropriate, directly. The databases and state directories are application-managed.
Profiles add another wrinkle. If you use named VS Code profiles, some settings live under User/profiles/<profile-id>/ rather than the root User/settings.json. So even “my settings file” can become plural.
The better name for User is a user-scoped state root. It contains what you configured, what VS Code remembered, and what extensions persisted on your behalf.
4. Global State and Workspace State Answer Different Questions#
globalStorage is for durable state that remains useful across workspaces. VS Code exposes APIs that allow extensions to save key-value state and larger files there.
Current installations commonly include a SQLite database named state.vscdb. It is a shared application store whose keys may belong to VS Code and to many extensions.
workspaceStorage answers a narrower question: what should be remembered for this particular folder or workspace?
User/workspaceStorage/
├── <opaque-workspace-id>/
│ ├── state.vscdb
│ ├── workspace.json
│ └── extension-owned data
└── ...
This state can reveal projects you opened, workspace paths, UI state, timestamps, feature state, or session-related artifacts. Some Copilot Chat versions and features have stored chat-related material in workspace-scoped directories too.
File names change. Features move. Remote development can place an extension on another host. Some activity is transient, some is remote, and some is never persisted here.
workspaceStorage is evidence of editor activity, not an audit log.
5. Local History Is the Memory Most Likely to Surprise You#
User/History backs VS Code’s Local History feature. When you save a file, VS Code can retain an entry containing the full contents of that saved version.
That is useful when Git cannot help you. Maybe you never committed the file. Maybe you overwrote a paragraph. Maybe you want the version from twenty minutes ago rather than yesterday’s commit.
The same feature creates a privacy consequence: removing text from the current file does not guarantee that the earlier saved text vanished from your machine.
save file with secret
|
v
local-history snapshot created
|
v
remove secret from current file
|
v
earlier snapshot may still contain it
Local History works around saves rather than keystrokes. VS Code documents defaults of 256 KB per entry and 50 entries per file, plus configurable exclusion patterns.
Still, this is a strong reason to keep secrets out of source files from the beginning. Deleting a secret later is cleanup, not prevention.
6. Extensions and Agent Plugins Are Executable Boundaries#
Ordinary extension packages live under:
~/.vscode/extensions/
Their persistent state may live under globalStorage or workspaceStorage. This gives us a useful separation:
| Location | What it answers |
|---|---|
~/.vscode/extensions | What extension code is installed? |
User/globalStorage | What cross-workspace state was persisted? |
User/workspaceStorage | What state belongs to a specific workspace? |
Project .vscode/ | What configuration belongs to the repository? |
Agent plugins introduce another location:
~/Library/Application Support/Code/agentPlugins/
An extension, a plugin, and a skill operate at different layers:
| Unit | What it is | What it can add |
|---|---|---|
| VS Code extension | Code installed into the editor | Commands, UI, language support, tools and contributed skills |
| Agent plugin | A distributable bundle of agent customizations | Skills, MCP servers and Copilot-specific agents, commands, rules or hooks |
| Agent skill | A task-specific folder loaded when relevant | Instructions plus referenced scripts, examples and resources |
A plugin is packaging. A skill is capability guidance.
The portable Agent Plugins 1.0 layout makes that relationship visible:
my-plugin/
├── plugin.json
├── skills/
│ └── test-runner/
│ ├── SKILL.md
│ └── run-tests.sh
├── mcp.json
└── com.github.copilot/
├── agents/
└── hooks/
SKILL.md is the entry point for a skill. Its frontmatter gives the skill a name and describes when it should load. Its body supplies the procedure. Supporting files are accessed when the instructions reference them, so installing many skills does not mean every skill is inserted into every prompt.
Skills can come from several scopes:
<repository>/.github/skills/ project skill
<repository>/.agents/skills/ project skill
<repository>/.claude/skills/ project skill
~/.copilot/skills/ personal skill
~/.agents/skills/ personal skill
~/.claude/skills/ personal skill
<installed-plugin>/skills/ plugin-distributed skill
That scope answers an ownership question. A repository skill travels with the project. A personal skill follows the user account on that machine. A plugin skill follows the installed plugin and its update lifecycle.
Skills can reference scripts and tell an agent to use tools. The command still passes through the client’s tool and permission controls, but the skill shapes what the agent attempts. Review a shared skill as an operational procedure rather than as documentation you will never execute.
Plugins raise the trust level further. A plugin can define hooks that run shell commands at lifecycle events, and it can bundle MCP servers that expose tools or external data. VS Code starts a plugin’s MCP servers when the plugin is enabled and stops them when it is disabled. Installing the plugin is therefore the meaningful trust decision; its MCP server does not receive a second workspace-style trust prompt.
A marketplace repository can also point at external packages, which makes its source and update policy part of the software supply chain.
That is why the marketplace reference matters. This source follows a moving branch:
github/awesome-copilot#marketplace
This source is pinned to an immutable snapshot:
github/awesome-copilot#<full-commit-sha>
Pinning does not make third-party code safe. It makes the code you reviewed the code you continue to run. Reproducibility comes first; trust still requires review.
7. Copilot CLI Has a Separate Home, With Deliberate Overlap#
~/.copilot belongs primarily to GitHub Copilot CLI. Depending on which features you use, it can contain settings, session state, logs, permissions, custom agents, skills, hooks, MCP configuration, installed plugins, and application-managed databases.
Files appear on demand. An absent installed-plugins or session-state directory does not mean the installation is broken; it may simply mean the feature has not created it yet.
VS Code can discover plugins installed by Copilot CLI under:
~/.copilot/installed-plugins/
That creates overlap between the clients without shared ownership. VS Code keeps its own user data in Application Support, while the CLI owns ~/.copilot.
The distinction becomes important when you change settings. Editing ~/.copilot/settings.json configures Copilot CLI. VS Code reads its own settings.json under Application Support, including any marketplace configuration.
8. Local State and Cloud Retention Are Separate Systems#
Local editor state, Copilot CLI session state, GitHub account synchronization, Copilot Memory, organization policy, and model-provider processing are separate systems. Their retention rules differ by plan, feature, client, policy, and provider.
Deleting a local directory is one operation. Deleting synchronized or server-side data is another.
Inspect local state for what it is: evidence stored by this client on this machine.
The Structure, in One Screen#
/Applications/Visual Studio Code.app
program bundle
~/Library/Application Support/Code/User/
preferences + global state + workspace state + local history
~/Library/Application Support/Code/agentPlugins/
VS Code-managed agent marketplaces and plugins
<repository>/.github/skills/ and ~/.copilot/skills/
project-owned and personal task-specific skills
/Library/
machine-wide resources shared by all users
/System/Library/
Apple-owned operating-system resources
~/.vscode/extensions/
ordinary extension packages
~/.copilot/
Copilot CLI settings, sessions, logs, and plugins
<repository>/.vscode and <repository>/.github/copilot
project-owned configuration
Four rules follow:
- Treat editor state and backups as sensitive.
- Treat extensions and agent plugins as executable dependencies.
- Treat skills as operational procedures that influence what an agent attempts.
- Treat local and cloud retention as separate questions.
Practical Hygiene#
Do not publish or commit your entire VS Code user-data directory. Do not casually attach it to a support ticket either.
Before sharing logs or database extracts, check for repository names, local paths, source fragments, prompts, account identifiers, remote URLs, and environment details. Prefer supported VS Code and Copilot commands over manually deleting rows from application-managed SQLite databases.
Review Local History settings for repositories containing sensitive data. Protect the Mac account and its backups with appropriate encryption and access controls. Review shared skills and plugin sources, pin versions where reproducibility matters, and test updates deliberately.
Do not wait until you discover a secret inside History to decide that local development state is part of your security boundary.
Closing Thoughts#
Modern development tools remember enough to make our work feel continuous. They restore windows, reopen workspaces, recover edits, load extensions, reconnect agents, and keep context alive across restarts.
That convenience creates a shadow architecture beside the repository: a local system of settings, databases, histories, plugins, caches, and logs that almost nobody inspects.
I set out looking for a settings file and found a state root instead. Your editor is part of your working environment, and its memory is part of your data estate.
Further reading#
- VS Code user and workspace settings
- VS Code language-model configuration
- VS Code MCP configuration reference
- Apple’s macOS Library directory details
- Apple’s guide to application support files
- VS Code extension data storage
- VS Code local file history
- Where VS Code extensions are installed
- Agent plugins in VS Code
- Agent Skills in VS Code
- GitHub Copilot CLI configuration directory
- About GitHub Copilot Memory