OpenCode stores configuration data in two main places: human-editable config files (your settings, providers, permissions, plugins, etc.) and an application storage directory (credentials, logs, and session data). For configuration files, the primary global config lives at ~/.config/opencode/opencode.json (JSON or JSONC), and you can also create project-level config files (like opencode.json at the project root) plus .opencode/ directories inside the repo for structured config (agents, commands, plugins, tools, themes, and so on). OpenCode merges these config sources rather than replacing them, so you can keep personal preferences global while letting each repo define its own tools or agent behavior.
The config system also has a clear precedence order. OpenCode can load an organizational “remote config” from a .well-known/opencode endpoint first (useful for team defaults), then merges global user config, then optional overrides from OPENCODE_CONFIG (a custom path) and OPENCODE_CONFIG_CONTENT (inline runtime overrides), then project config (opencode.json), and finally .opencode directories that hold modular pieces like tools/, plugins/, commands/, agents/, and themes/. This matters because it explains why a setting “won’t stick”: you may be editing the global config while a project config overrides the same key, or your org’s remote config sets defaults you didn’t realize existed. If you want your repo to be portable for teammates, put repo-specific behavior under .opencode/ and keep secrets out of it; if you want stable personal behavior everywhere, keep it in ~/.config/opencode/opencode.json and only override per project when necessary.
Separately from config files, OpenCode keeps application data on disk under ~/.local/share/opencode/ on macOS/Linux, and on Windows you can open WIN+R and paste %USERPROFILE%\.local\share\opencode. That directory contains auth.json (provider credentials like API keys and OAuth tokens), a log/ directory (application logs), and project/ data for sessions and messages. If your project is in a Git repo, the per-project storage is organized under a project slug; if it isn’t a Git repo, OpenCode uses a global storage area. This storage layout becomes relevant when you build systems that integrate with external services—like a local RAG app that talks to Milvus or Zilliz Cloud—because you’ll often want to keep environment-specific settings (database endpoints, test keys, staging flags) outside your repo and in your user-level config or environment variables, while keeping the repo’s .opencode/tools/ and .opencode/agents/ committed for repeatable workflows.
