VixlVixl
Docs
Changelog
GitHub
Docs
Changelog
GitHub
  • Get Started

    • Overview
    • Philosophy
    • Installation
    • Set up providers and models
    • Add a project
    • Create a project group
    • Your first chat
  • Concepts

    • How Vixl works
    • Chat modes
    • Permissions and approvals
    • Projects and home chats
    • Models and roles
    • Context
    • Code graphs
    • The .vixl directory
  • Using Vixl

    • Manage chats
    • Queue and stop messages
    • Review and restore changes
    • Compact and hand off long chats
    • Export a transcript
    • Work with plans
    • Orchestrate sub-agents
    • Best practices
    • Use the workbench
    • Shortcuts and the command palette
  • Customize

    • Providers
    • Models
    • MCP servers
    • Skills
    • Custom agents
    • Rules and AGENTS.md
    • Language servers
    • Appearance
    • Permission settings
  • Reference

    • settings.json
    • mcp.json
    • Custom agent frontmatter
    • SKILL.md format
    • Keyboard shortcuts
    • Chat statuses
    • .vixl layout
    • Managed components
  • Resources

    • Troubleshooting
    • FAQ
    • Privacy
    • Comparison
    • Roadmap
    • Brand and press
    • Changelog

settings.json

settings.json is the on-disk store for theme, models, permissions, sandbox, MCP trust, and similar preferences. Personal settings live at ~/.vixl/settings.json. A project can add <repo>/.vixl/settings.json to overlay some of those keys. API keys never go in this file; they stay in the OS keychain. Paths: .vixl layout. Keys: Providers.

The file is a JSON object with "version": 1. A missing or empty file loads as the defaults below. An invalid file, or one whose version is not 1, also loads as those defaults. Unknown keys that still parse as a string, number, boolean, array, or custom provider object are kept. Deprecated keys (agent.defaultProvider, agent.defaultModel, chat.autoTitleModel, agent.defaultMode, fleet.maxConcurrentAgents, fleet.trayBackground, general.machineLabel) are dropped on load.

Personal vs project

Home chats use the personal file only. A project whose root is your user home directory also uses the personal file only: project-scope reads are empty and project-scope writes are refused. Other project chats merge personal settings with that project's file.

Project values replace personal values for most keys that appear in the project file. Keys that start with providers., models., or lsp. are personal only. If they appear in a project file, Vixl strips them and rewrites the file.

These keys merge instead of replace:

KeyMerge
agent.mcp.trustUnion by serverId. Personal never wins. Otherwise the project record wins.
agent.permissionsUnion by capability. Personal deny wins, then project deny, otherwise the project record.
agent.autoApproveGlobsUnion of both string lists, personal first, duplicates dropped.

A project file that fails to parse contributes no overrides (the personal file still applies). Keys omitted from the project file keep the personal value.

Keys

Scope is personal (ignored and stripped from a project file) or overridable (a project value replaces the personal one, except the three merge keys above).

KeyTypeDefaultScope
version11Required in both files
appearance.theme"light" | "dark" | "system""system"Overridable
appearance.transparencybooleantrueOverridable
appearance.transparencyHuenumber 0 to 360265Overridable
appearance.transparencyIntensitynumber 0 to 1000Overridable
agent.autoApproveGlobsstring[][]Union
agent.permissionLevel"ask" | "allowlist" | "bypass""allowlist"Overridable
agent.permissionspermission records[]Union by capability
agent.mcp.trusttrust records[]Union by serverId
agent.sandbox.enabledbooleantrueOverridable
agent.sandbox.network"deny" | "allow""allow"Overridable
lsp.autoDownloadbooleantruePersonal
workspace.trust{ rootPath, trusted }[][]Overridable (replaces the whole array)
chat.autoTitlebooleantrueOverridable
workbench.duplicateTabBehavior"ask" | "open-existing" | "open-new""ask"Overridable
models.defaultmodel refunsetPersonal
models.askmodel refunsetPersonal
models.planmodel refunsetPersonal
models.agentmodel refunsetPersonal
models.orchestratormodel refunsetPersonal
models.subagentmodel refunsetPersonal
models.titlemodel refunsetPersonal
models.*Reasoningreasoning levelunsetPersonal
models.catalogOptionsmap of model ref to optionsunsetPersonal
models.catalogMetamap of model ref to catalog metaunsetPersonal
providers.<id>.apiKeyRefstringunsetPersonal
providers.custom.<id>custom provider objectunsetPersonal

Model fields have no defaults. First run has no providers and no default model. See Models and roles.

Appearance

appearance.theme follows Light, Dark, or the OS. appearance.transparency turns window transparency on. When it is on, appearance.transparencyHue (0 to 360) and appearance.transparencyIntensity (0 to 100) set the tint. Edit these in Appearance.

Agent, sandbox, and permissions

agent.permissionLevel is the chat permission dial: Ask, Allowlist, or Bypass. See Permissions and approvals.

agent.permissions is the persisted allow and deny list. Each record is:

{
  "capability": "fs.write",
  "verdict": "allow",
  "scope": "workspace"
}

capability is a string such as fs.write, fs.delete, fs.write:<path>, fs.delete:<path>, shell, shell.network, shell.unsandboxed, git.commit, git.checkout, git.branch_create, mcp:<serverId>, mcp:<serverId>:<tool>, web.fetch, web.fetch:<host>, or workspace.move. verdict is "allow" or "deny". scope on disk is "workspace" or "always" (once and session are not persisted).

agent.autoApproveGlobs auto-approves filesystem writes and deletes when every path matches at least one glob (dotfiles included). There is no Settings form for this list. Edit the JSON. An empty list means those actions still ask (unless Bypass already allows them).

agent.sandbox.enabled sandboxes agent terminal commands. agent.sandbox.network is "allow" or "deny" for network inside that sandbox. Leaving the sandbox always asks. See Permission settings.

MCP trust

agent.mcp.trust records whether a server may start. Each record is:

{
  "serverId": "github",
  "scope": "always",
  "fingerprint": "ab12cd34ef56ab78"
}

scope is "session" | "workspace" | "always" | "never". fingerprint is a hash of the command plus args (stdio) or of the transport type plus URL (HTTP/SSE). Missing fingerprint means untrusted until granted again. Changing command, args, URL, or HTTP vs SSE requires trust again. See mcp.json.

Workspace trust

workspace.trust is an array of { "rootPath": string, "trusted": boolean }. Project-local language servers that require trust (ESLint, Oxlint, Biome) check this list against the canonical project root.

Models

Each role stores a model ref providerId::modelId. Optional reasoning for that role is a separate field.

FieldRole
models.defaultFallback for every role
models.askAsk mode
models.planPlan mode
models.agentAgent mode
models.orchestratorOrchestrator parent
models.subagentNested sub-agent default
models.titleBackground chat titles

Reasoning fields: models.defaultReasoning, models.askReasoning, models.planReasoning, models.agentReasoning, models.orchestratorReasoning, models.subagentReasoning, models.titleReasoning. Allowed values: "provider-default", "none", "minimal", "low", "medium", "high", "xhigh", "max".

models.catalogOptions is a map from model ref to { reasoning?, fast?, allowed?, contextWindow?, maxOutputTokens? }. models.catalogMeta is a map from model ref to { contextWindow?, maxOutputTokens?, pricing?, fastPricing?, vision?, toolCalling? }. Pricing uses USD per million tokens: inputPerMillion, outputPerMillion, optional cacheReadPerMillion, cacheWritePerMillion, reasoningPerMillion.

chat.autoTitle turns background title generation on. Edit roles in Models.

Providers

Catalog providers store only a keychain pointer:

"providers.openai.apiKeyRef": "openai"

The secret itself is vixl:provider:<apiKeyRef> in the keychain. See Providers.

Custom OpenAI-compatible endpoints use providers.custom.<id>:

{
  "type": "openai-compatible",
  "name": "local",
  "baseURL": "http://localhost:1234/v1",
  "apiKeyRef": "local",
  "headers": {},
  "queryParams": {},
  "includeUsage": true,
  "supportsStructuredOutputs": false,
  "models": []
}

type must be "openai-compatible". name is required. baseURL must be a URL. apiKeyRef, headers, queryParams, includeUsage, supportsStructuredOutputs, and models are optional. When includeUsage is omitted, Vixl treats it as true. Each model object requires id and may set name, maxInputTokens, maxOutputTokens, contextWindow, toolCalling, vision, thinking, streaming, supportsReasoningEffort, reasoningEffort, temperature (0 to 2), topP (0 to 1), topK, frequencyPenalty (-2 to 2), presencePenalty (-2 to 2), seed, headers, modelOptions, pricing, and fastPricing.

Other fields

lsp.autoDownload downloads default language support when a project is activated. Disable it for airgapped machines. Server install state lives in personal lsp.json, not here. See Language servers and Managed components.

workbench.duplicateTabBehavior controls what happens when you open a Terminal tab that is already open for that project: ask, reuse the existing tab, or open a new one. Editor tabs do not use this setting: there is one editor tab per project, and opening a file adds it there.

Example

{
  "version": 1,
  "appearance.theme": "system",
  "appearance.transparency": true,
  "models.default": "anthropic::claude-sonnet-4-5",
  "models.agent": "anthropic::claude-sonnet-4-5",
  "agent.permissionLevel": "allowlist",
  "agent.autoApproveGlobs": ["src/**", "docs/**"],
  "agent.sandbox.enabled": true,
  "agent.sandbox.network": "allow",
  "chat.autoTitle": true,
  "workbench.duplicateTabBehavior": "ask",
  "lsp.autoDownload": true,
  "agent.mcp.trust": [
    { "serverId": "github", "scope": "always", "fingerprint": "ab12cd34ef56ab78" }
  ],
  "workspace.trust": [
    { "rootPath": "/Users/you/src/vixl", "trusted": true }
  ]
}

See mcp.json for MCP server configs and .vixl layout for every path.

Edit this page
Last Updated: 10/11/26, 7:48 PM
Next
mcp.json