Configuration & profiles
What configuration is
Section titled “What configuration is”Every CLI in scope has a hierarchy of configuration locations: a project-level file checked into the repo, a user-level file in your home directory, and optional managed-policy overrides for orgs. These files hold the settings that don’t belong in a prompt or a skill — the default model, permission rules, MCP server registrations, hooks, theme, output format defaults.
Codex is the only tool in scope with named profiles — separate config bundles in the same file that you swap with --profile <name> at launch. Claude Code and opencode achieve a similar feel through different mechanisms (local-settings files; per-agent customisation). Cursor and Copilot ride VS Code’s settings.json model — Cursor adds a .cursor/ directory at the repo root for its native assets; Copilot’s settings live under the github.copilot.* and chat.* namespaces, plus repo-level files under .github/ and org-level policy on github.com.
Why you’d want to think about this
Section titled “Why you’d want to think about this”You wanted to change the default model to the cheaper one. Twenty minutes later you’ve got three browser tabs open, one for each tool’s docs, and you’ve discovered: there’s a project setting, a user setting, an environment variable, a TOML profile, a managed config, and a flag, and they all interact, and the one you edited isn’t the one that’s winning, and you can’t actually tell which one is winning because nothing in the TUI says.
Or: you’ve got a “safe” setup you use for client repos (ask before every shell command, deny edits to anything outside the workspace) and a “wide open” setup you use for personal projects (allow everything, never ask). You currently swap between them by hand-editing the settings file every time, which is exactly the kind of fiddly chore you started using the CLI to avoid.
That’s the gap configuration design closes. Once you know where each setting lives, which layer wins, and what mechanism your tool uses for swapping setups (Codex profiles, Claude Code local-settings, opencode primary agents), the chore becomes a flag. “Use the safe setup” becomes codex --profile safe — once.
Real-world examples of what teams put in configuration (vs. in code or skills):
- Default model — pin Sonnet for the project so contributors don’t all use whatever they happen to default to. See Model selection.
- Permission policy — the team’s allow/ask/deny rules, checked in so everyone gets the same guardrails. See Permissions.
- MCP server registrations — your repo’s Postgres/Linear/Figma adapters wired up once, in
.mcp.json/config.toml/opencode.json. See MCP servers. - Hook bindings — declarative event handlers (lint after edit, block pushes to main). See Hooks.
- Personal overrides — Claude Code’s
settings.local.json(gitignored) for your machine-specific quirks: a different model, a noisier hook, an extra debugging MCP server. - Org policy — managed config that mandates: deny
Bash(rm:*), require approval forBash(*), force a specific model. Cannot be overridden by user settings. - Profile bundles (Codex) —
--profile work(sandboxed, conservative),--profile yolo(full access, never asks),--profile review(read-only, untrusted). Swap by flag.
The test: if the same setting is being typed at the CLI more than once, or copy-pasted between files, it belongs in configuration.
Why this and not…
Section titled “Why this and not…”| You want to… | Reach for | Not |
|---|---|---|
| Pin defaults that survive across sessions (model, theme, output format) | Configuration file | Env vars per session |
| Share team settings via the repo | Project config (checked in) | User config |
| Keep personal overrides off git | Claude Code settings.local.json / shell env | Project config |
| Swap between named setups with one flag | Codex profile | Editing the file each time |
| Distribute config + skills + hooks + MCP as one unit | Plugin | Raw config |
| Enforce org-wide policy that can’t be overridden | Managed config | Project / user files |
| Give one agent a different posture than another (opencode) | Custom primary agent | A second profile |
Configuration is for defaults and policy. Skills, hooks, MCP servers, and subagents are still where the behaviour lives — config just enables them and sets their defaults. If you find your config file growing into a procedure, you wanted a skill.
How it works in each tool
Section titled “How it works in each tool”Locations:
.claude/settings.json— project (checked in).claude/settings.local.json— project (gitignored, your local overrides)~/.claude/settings.json— user- Managed-policy
settings.json— org-controlled
Layering: managed > user > project local > project shared. Each level can set permissions, hooks, MCP servers, skill overrides, and other knobs.
Settings categories:
permissions— see Permissionshooks— see HooksskillOverrides— hide or expose specific skills without editing themmodel— default model for this scope- Misc TUI knobs (theme, status line)
Claude Code does not have named profiles. Each scope’s settings.json is the only config for that scope at a time. To swap configs, you change the file (or move it).
Locations:
.codex/config.toml— project (gated by directory trust)~/.codex/config.toml— user- Managed config — org-controlled
Project-level config only applies if the directory is marked trusted. Trust is configured in TOML via:
[projects."/abs/path/to/repo"]trust_level = "trusted"Named profiles are Codex’s distinguishing feature. Define multiple configs in the same file and select one at launch:
[profiles.work]model = "gpt-5-..."sandbox = "workspace-write"
[profiles.yolo]model = "gpt-5-..."sandbox = "danger-full-access"approval_policy = "never"Then: codex --profile work or codex --profile yolo.
Feature flags: the [features] table toggles optional and experimental capabilities (set feature_name = true). Profiles themselves are marked experimental in the current docs.
Locations:
opencode.json— project~/.config/opencode/opencode.json— user (global)OPENCODE_CONFIG/OPENCODE_CONFIG_DIRenv vars for custom paths- Managed/system config for org-wide policy
Layering: sources are merged, not replaced. Among the standard config files, project config has the highest precedence and overrides global/remote where they overlap. Managed config layers above that.
No named profiles in the Codex sense — per-agent customisation (via primary agents) substitutes for many of the same use cases. You’d define a “yolo” primary agent rather than a “yolo” profile.
Cursor inherits VS Code’s settings model. User settings live in the platform-specific Cursor/User/settings.json (e.g. ~/Library/Application Support/Cursor/User/settings.json on macOS). Project settings in .vscode/settings.json are honoured.
Cursor-specific surfaces:
.cursor/at the repo root holds Cursor-specific assets:rules/,commands/,skills/,agents/,mcp.json,hooks.json,environment.json.~/.cursor/holds the user-scope equivalents.- CLI config has a notable constraint: only permissions can be set per-project; all other CLI settings are global.
- Team / Enterprise config is pushed from the Cursor dashboard, including Team Rules and Team Commands.
Environment variables: CURSOR_API_KEY for headless / CI auth. Other env vars unverified.
Cursor does not currently have a single canonical cursor.config.json analogous to opencode.json; configuration is spread across several files in .cursor/ plus VS Code’s settings.json. No named profiles in the Codex sense.
Copilot rides VS Code’s settings.json. Two namespaces dominate: github.copilot.* and chat.*.
Key VS Code settings:
github.copilot.chat.codeGeneration.useInstructionFiles— auto-applycopilot-instructions.mdchat.instructionsFilesLocations— where to find.instructions.mdfiles (default includes.github/instructions)chat.promptFilesLocations— prompt-file directories (default.github/prompts)chat.agentSkillsLocations— extra skill directorieschat.useCustomizationsInParentRepositories— walk up for monorepo parent configschat.agent.enabled— toggle agent mode (VS Code 1.99+)chat.agent.sandbox.enabled— sandbox shell callschat.mcp.access,chat.mcp.discovery.enabled,chat.mcp.apps.enabledchat.permissions.default,chat.tools.*.autoApprovechat.planAgent.defaultModel,inlineChat.defaultModel,chat.utilityModel,chat.utilitySmallModel
Repo-level config:
.github/copilot-instructions.md,.github/instructions/,.github/prompts/,.github/skills/.vscode/mcp.json(VS Code MCP)
Org-level (github.com → Org Settings → Copilot, Business/Enterprise):
- Custom instructions, model allow/deny, content exclusions, MCP policy, extension/plugin policy.
No named profiles à la Codex. JetBrains and other IDEs have plugin-specific preference panes; parity with VS Code’s settings catalog lags. Unverified as of 2026-05-21 exactly which VS Code settings have JetBrains equivalents.
Comparison
Section titled “Comparison”| Aspect | Claude Code | Codex | opencode | Cursor | Copilot |
|---|---|---|---|---|---|
| Project config | .claude/settings.json | .codex/config.toml (in trusted dirs) | opencode.json | .vscode/settings.json + .cursor/ (rules, mcp, hooks, etc.) | .github/copilot-instructions.md, .github/instructions/, .vscode/mcp.json |
| Local-only project config | .claude/settings.local.json (gitignored) | — | — | — | — |
| User config | ~/.claude/settings.json | ~/.codex/config.toml | ~/.config/opencode/opencode.json | Cursor/User/settings.json (platform path) + ~/.cursor/ | VS Code user settings.json + ~/.copilot/ (CLI) |
| Format | JSON | TOML | JSON | JSON (VS Code) + assorted files under .cursor/ | JSON (VS Code settings.json) |
| Managed/org overrides | Yes | Yes (managed configs) | Yes (managed configs) | Yes (Team / Enterprise dashboard) | Yes (github.com org policy, Business/Enterprise) |
| Named profiles | No | Yes (--profile) | No (use primary agents) | No | No |
- In Claude Code, use
settings.local.jsonfor anything you don’t want checked in — model overrides, personal hook scripts, allow rules unique to your machine. - In Codex, profiles are the cleanest way to switch between a “safe” work setup and a YOLO experimentation setup without retyping flags.
- In opencode, don’t try to emulate Codex profiles by swapping
opencode.json— define custom primary agents instead. - In Cursor and Copilot, the IDE’s
settings.jsonis the source of truth — check.vscode/settings.jsoninto the repo for shared defaults, then let usersettings.jsonoverride.
Name collisions
Section titled “Name collisions”- “Profile” in Codex means a named config bundle. The word doesn’t mean the same thing in Claude Code or opencode — both use “settings level” or “scope.”