Configuration File

Posit Assistant is configured through a JSON settings file. This file controls model selection, behavior preferences, runtime configuration, permissions, and more.

File Locations

📝 Directory change

In previous versions, the configuration directory was ~/.positai (global) and .positai/ (project-level). These have been renamed to ~/.posit/assistant and .posit/assistant/. Existing files are migrated automatically on first launch.

Posit Assistant uses two levels of configuration:

  • Global config applies to all projects. Located at:

    • macOS / Linux: ~/.posit/assistant/settings.json
    • Windows: %USERPROFILE%\.posit\assistant\settings.json
  • Project config overrides global settings for a specific project. Place a .posit/assistant/settings.json file in your project root.

Some settings (like providers, storage, and logging) are global-only. Others (like model, permissions, and MCP servers) can be set at either level, with project values taking precedence. The sections below indicate which level each setting supports.

Settings are resolved in this order (last wins): defaults → global config → project config → environment variables → CLI flags.

In a managed deployment your administrator can add two more layers, one below everything and one above everything. See Administrator-Managed Settings.

Editor Schema

A JSON Schema for the global settings file is hosted at a stable URL:

https://assistant.posit.co/schemas/settings.schema.json

Reference it from the $schema field of your global ~/.posit/assistant/settings.json to get hover documentation and validation in editors like VS Code and Positron:

{
  "$schema": "https://assistant.posit.co/schemas/settings.schema.json"
}
⚠️ Global config only

The hosted schema validates the global file. Project-level .posit/assistant/settings.json files allow keys the global schema forbids (such as tools.allowed and tools.blocked), so do not reference this URL from a project file — your editor would flag valid configuration.

Per-Project Settings

The following settings can be set in either the global ~/.posit/assistant/settings.json or a project-level .posit/assistant/settings.json. Project values take precedence over global values.

Model Settings

Use modelTiers to prefer particular models for internal low, medium, and high work by subagents, for project exploration, conversation summaries, and delegated web search. These tiers only affect internal work — the model for your main conversation is still controlled by model.id. Each value is an ordered list of case-insensitive substrings matched against model IDs on the current provider:

{
  "modelTiers": {
    "low": ["luna", "haiku"],
    "medium": ["terra"],
    "high": ["sol", "opus", "pro"]
  }
}

The first substring with any matches wins; when it matches multiple versions, Posit Assistant uses the newest. Unmatched entries are skipped. All three keys are optional. Changes take effect on the next model resolution without restarting the assistant.

A preference that exactly names a model — its full ID or the part of the ID after the last / — takes precedence over substring matching. This disambiguates models where one ID is a prefix of another: Posit AI Pass lists both zai-org/GLM-5.3 and zai-org/GLM-5.3-Flash, and "medium": ["glm-5.3"] selects the regular GLM-5.3 because it names that model exactly, while "glm-5.3-flash" selects the Flash variant. Without exact matching, no substring of glm-5.3 could exclude the Flash model.

Preferences that name only a version track the newest release: with GLM-5.2, GLM-5.3, and GLM-5.3-Flash all available, "medium": ["glm-5"] selects GLM-5.3. When several models tie on the newest version, the base model wins over suffixed variants like Flash — name the variant in the preference if you want it.

Each tier also accepts an object form that sets a default thinking effort for subagents launched on that tier:

{
  "modelTiers": {
    "low": { "models": ["luna", "haiku"], "thinkingEffort": "low" },
    "high": { "models": ["sol", "opus", "pro"], "thinkingEffort": "max" }
  }
}

The thinking effort default applies when a subagent launch does not pass an explicit thinkingEffort; without either, subagents default to "medium". A default the resolved model does not support maps to its nearest supported level (ties round down), falling back to the provider’s own default behavior only when the model has no mappable level.

Project and global modelTiers settings merge per tier: a project high entry replaces the global high entry wholesale (object form included) while omitted project low and medium entries continue to use the global ones. The safety classifier deliberately ignores these preferences.

Tier requests (low, medium, or high) check the same-named list before built-in defaults. The launchSubagent tool also accepts default, which reuses the model launching the subagent. Concrete model names are server policy rather than tool request values. Built-in fallbacks prefer the launching model’s family, then may select another family on the same provider, and finally inherit the launching model. Model selection never changes providers.

KeyTypeDefaultDescription
modelTiers.lowstring[] | { models: string[], thinkingEffort?: string }[]Ordered model-ID substrings preferred for low-tier internal work, with an optional default thinking effort for subagents. The first substring with a match wins.
modelTiers.mediumstring[] | { models: string[], thinkingEffort?: string }[]Ordered model-ID substrings preferred for medium-tier internal work, with an optional default thinking effort for subagents. The first substring with a match wins.
modelTiers.highstring[] | { models: string[], thinkingEffort?: string }[]Ordered model-ID substrings preferred for high-tier internal work, with an optional default thinking effort for subagents. The first substring with a match wins.
model.idstring"claude-sonnet-4-6"The model to use for conversations.
model.providerstring"positai"The LLM provider. The default is "positai" (Posit AI Pass — a managed service from Posit). See the Posit AI Pass page for details.
model.thinkingEffortstringDefault thinking effort level for new conversations. During a conversation, thinking effort is adjusted via the UI and stored per-conversation.
model.webSearchbooleanfalseDefault web search preference for new conversations. During a conversation, web search is toggled via the UI and stored per-conversation.

Permissions

Control which capabilities the assistant can use. Each key is a permission key, usually a tool name (bash, read, edit, etc.), mapped to either an action string or an object of patterns for that capability’s match target. For example, bash patterns match commands, while task patterns match the subagent type requested through launchSubagent:

{
	"permission": {
		"bash": {
			"git *": "allow",
			"rm *": "deny"
		},
		"read": "allow",
		"edit": "ask",
		"task": {
			"explore": "deny",
			"general": "ask"
		}
	}
}

The former permission.explore key is no longer supported. Move its "allow", "ask", or "deny" value to permission.task.explore.

You can also set a single action for all tools as a shorthand:

{
	"permission": "ask"
}
KeyTypeDefaultDescription
permissionstring | objectPermission configuration. Set to "allow", "ask", or "deny" for all capabilities, or use per-key rules whose patterns match the relevant input, such as shell commands, file paths, or subagent types.
📝 Project vs. global permissions

When you grant or deny permissions through the UI, they are saved to your project-level .posit/assistant/settings.json. If you want permissions to apply across all projects, copy the permission block to your global ~/.posit/assistant/settings.json instead.

MCP Servers

Connect external tool servers using the Model Context Protocol.

{
  "mcpServers": {
    "my-server": {
      "type": "local",
      "command": ["node", "server.js"],
      "environment": {
        "API_KEY": "..."
      }
    },
    "remote-server": {
      "type": "remote",
      "url": "https://mcp.example.com",
      "headers": {
        "Authorization": "Bearer ..."
      }
    }
  }
}
KeyTypeDefaultDescription
typestring"local"Server type. "local" for stdio subprocess, "remote" for HTTP/SSE.
commandstring[]Command and arguments to start a local MCP server.
urlstringURL of a remote MCP server.
enabledbooleantrueWhether this server is active.
timeoutnumber10000Connection timeout in milliseconds.
📝 Project vs. global MCP servers

MCP servers can be configured in either the project-level .posit/assistant/settings.json or the global ~/.posit/assistant/settings.json. Project-level servers are merged with global servers by server name, with project values taking precedence. Project-level servers — and a project-level mcp admission policy — apply only in a trusted workspace; they are dropped entirely while the workspace is untrusted. Use project-level config for project-specific servers and global config for servers you want available everywhere.

The sibling mcp key controls which configured servers may run at all — see Admission Policy.

Skills

Control where Posit Assistant discovers custom skills.

KeyTypeDefaultDescription
skills.pathsstring[]["~/.agents/skills", "~/.posit/assistant/skills", ".agents/skills", ".posit/assistant/skills"]Directories to search for skills, processed in order. Paths starting with ~ or $HOME are expanded to the home directory. Relative paths are resolved against each workspace root.
📝 Skill name conflicts

When the same skill name exists in more than one directory, the version from the later directory is used.

📝 Project vs. global skill paths

When both global and project-level configs define skills.paths, the project value completely replaces the global value — paths are not merged. To extend the defaults, repeat them in your project config alongside any additions.

Plugins

Register plugin marketplaces and control which plugins are enabled. These keys are normally managed for you by the plugin manager, but you can also edit them directly. See Plugins & Marketplaces for the full feature guide.

{
  "extraKnownMarketplaces": {
    "acme": { "source": "acme/plugins" }
  },
  "enabledPlugins": {
    "data-tools@acme": true
  }
}
KeyTypeDefaultDescription
extraKnownMarketplacesobject{}Declared plugin marketplaces, keyed by name. Each value gives the marketplace source (a GitHub owner/repo, a git URL, or a local path). Readable from a project config in a trusted workspace, where it merges with your global marketplaces.
enabledPluginsobject{}Plugin enablement keyed by "<plugin>@<marketplace>". true = enabled, false = installed but disabled, absent = not installed. Readable from a project config in a trusted workspace, where it merges with your global entries.
plugins.allowedComponentsstring[]all typesRestrict which component types a plugin may contribute (e.g. ["skills", "commands", "mcpServers"]). Unknown values are ignored. Omitted means no restriction. A project config can narrow this further but never widen it.
plugins.hostTokensobject{}Per-host git credential references for private marketplaces, as {env:VAR} environment-variable references only. Global scope only, so a project config cannot inject credentials.
plugins.strictKnownMarketplacesarrayMarketplace allowlist. Omitted means open (any marketplace); [] means no marketplace is allowed; a non-empty list allows only matching marketplaces. Each entry is a matcher: {"source":"github","github":"owner/repo"}, {"source":"url","url":"..."}, {"source":"hostPattern","hostPattern":"..."} or {"source":"pathPattern","pathPattern":"..."} (the two pattern forms are regular expressions). Global scope only.
plugins.blockedMarketplacesarrayMarketplace denylist, using the same matcher entries as strictKnownMarketplaces. A match is blocked regardless of the allowlist. Global scope only.
📝 Marketplace lists are strict

Unlike plugins.allowedComponents, which ignores values it doesn’t recognize, an unusable entry in strictKnownMarketplaces or blockedMarketplaces — an unknown source, or a pattern that isn’t a valid regular expression — is a validation error rather than being quietly skipped. A silently dropped denylist entry would leave a marketplace reachable with nothing saying why.

📝 Project vs. global plugin keys

extraKnownMarketplaces, enabledPlugins, and plugins.allowedComponents can each be set globally or in a project config, and the plugin manager lets you choose which file it writes to. Project entries are only read in a workspace you have trusted, and they add to rather than replace your global entries. Downloaded plugin content always lives in your per-user store (~/.posit/assistant/plugins/) regardless of which config declared it. plugins.hostTokens is global-only and is never read from a project config, so a repository can never supply git credentials.

💡 Enterprise administration

Administrators can enforce a marketplace allowlist and denylist, a component ceiling, managed marketplaces, and non-overridable plugin enablement on every platform, by delivering these keys through POSIT_ASSISTANT_SETTINGS_ENFORCED, the only channel for the plugin lockdown. If you have also written a lockdown in your own settings.json, the two combine rather than replace, and neither can loosen the other. See Plugins.

Runtime Settings

Control how Posit Assistant connects to R and Python.

KeyTypeDefaultDescription
runtime.r.enabledbooleantrueEnable R runtime integration.
runtime.r.pathstring"Rscript"Path to the Rscript executable.
runtime.r.timeoutnumber30000Timeout in milliseconds for R code execution.
runtime.python.enabledbooleantrueEnable Python runtime integration.
runtime.python.pathstring"python3"Path to the Python executable.
runtime.python.timeoutnumber30000Timeout in milliseconds for Python code execution.

Workspace Settings

KeyTypeDefaultDescription
workspace.pathstring""Working directory. Defaults to the current directory.
workspace.allowedRootsstring[]Allowed root directories for workspace switching. Defaults to the user home directory.

Sandbox

Control sandbox mode for shell tool execution. On macOS and Linux, bash commands run inside an OS-level sandbox (macOS Seatbelt / Linux bubblewrap) that restricts writes to the workspace and temp directories, blocks network access, and prevents reading sensitive paths like ~/.ssh and ~/.aws. On Windows, the same setting enables gated mode for the active shell: commands are checked against a built-in allowlist before they run. This is not an OS-level sandbox.

KeyTypeDefaultDescription
sandbox.enabledbooleanfalseEnable sandboxing for shell tool execution.

You can also toggle sandbox mode during a session with the /sandbox command.

Tips

Control the helpful tips that appear above the input area. A tip always appears on startup; after each assistant turn, a tip appears with a small probability.

KeyTypeDefaultDescription
features.showTipsbooleantrueShow tips above the input after assistant turns and on startup.
💡 Positron users

In Positron, this setting is also available as assistant.showTips in the Settings UI. See Positron Settings for how values from both sources are merged.

Compaction

Control how Posit Assistant manages long conversations. See Context Management for details on how compaction works.

These settings go in the features block of your config file:

{
  "features": {
    "autoCompactTokenBuffer": 30000
  }
}
KeyTypeDefaultDescription
features.autoCompactTokenBuffernumber30000Tokens reserved for the compaction summary. Auto-compaction triggers once fewer than this many tokens remain in the context window.

Micro-compaction is controlled by the /microcompact command, not configuration. It runs only when you invoke it.

💡 Positron users

In Positron, compaction settings are read from the config file’s features block. assistant.autoCompactTokenBuffer can also be set via Positron’s settings.json, though it is not exposed in the Settings UI. See Positron Settings for how values from both sources are merged.

Cache Keepalive

Keep a supported model’s prompt cache warm while you read a response and step away. When enabled, Posit Assistant sends lightweight background “pings” after each turn so a follow-up message can reuse the cached conversation prefix. Cache lifetime and ping cadence depend on the selected model.

This is on by default. To turn it off or bound how long pings may be sent, set the features block in your settings file:

{
  "features": {
    "cacheKeepalive": false,
    "cacheKeepaliveMinutes": 30
  }
}
KeyTypeDefaultDescription
features.cacheKeepalivebooleantrueEnable cache-keepalive pings after a turn completes for models with a supported cache policy.
features.cacheKeepaliveMinutesnumber30Maximum wall-clock window after the last real model request during which automatic pings may be sent (0–60 minutes). This is a send deadline, not the cache-expiration time.
📝 Model-dependent timing

Claude and supported GPT-5.6 routes use different cache lifetimes and ping cadences. A successful final ping can keep the cache warm beyond the configured ping-send window. Changes to cacheKeepalive and cacheKeepaliveMinutes take effect on your next turn — no restart needed.

💡 Positron users

In Positron, these settings are also available as assistant.cacheKeepalive and assistant.cacheKeepaliveMinutes in Positron’s Settings UI. When set in both places, Positron merges them — see Positron Settings for priority order.

Global Settings

The following settings can only be set in the global ~/.posit/assistant/settings.json. They are not supported in project-level config files.

Provider Settings

Provider connection details use a separate global file, ~/.posit/ai/providers.json, not the ~/.posit/assistant/settings.json documented above. That file has its own reference page covering every key, including model discovery and filtering, per-protocol endpoints, the provider-specific sections, and custom providers.

See providers.json for the full reference, and Providers for the list of supported providers and setup instructions.

Storage Settings

KeyTypeDefaultDescription
storage.pathstring"~/.posit/assistant"Directory for conversation storage.

Logging

KeyTypeDefaultDescription
logging.levelstring"info"Log level. Options: "error", "warn", "info", "debug", "trace".
logging.filestring""Log file path. Defaults to ~/.posit/assistant/logs/{platform}.log.
logging.consolebooleantrueOutput logs to the console.

Example Configuration

{
  "model": {
    "provider": "positai",
    "id": "claude-sonnet-4-6"
  },
  "permission": {
    "read": "allow",
    "bash": {
      "git *": "allow"
    },
    "task": {
      "explore": "deny",
      "general": "ask"
    }
  },
  "skills": {
    "paths": [
      "~/.agents/skills",
      "~/.posit/assistant/skills",
      ".agents/skills",
      ".posit/assistant/skills",
      "~/my-company/shared-skills"
    ]
  }
}
📝 Changes take effect on restart

Some configuration changes require restarting the assistant or opening a new conversation to take effect.

Developer Settings

No stability guarantees

The settings in this section are experimental or developer-facing. They may change, break, or be removed between releases without notice. Use them at your own risk. Documentation here may lag behind the actual behavior.

These settings go in the features block of your config file and can be set at either global or project level. For example:

{
  "features": {
    "experimentalFeatures": true,
    "cacheKeepaliveWidget": true
  }
}
KeyTypeDefaultDescription
features.experimentalFeaturesbooleanfalseEnable experimental in-development features. Gates access to new capabilities that are still being refined, including the plugin & marketplace manager and its /plugin and /marketplace commands.
features.devModebooleanfalseEnable developer debugging surfaces such as raw tool data display, conversation path copying, and dev-only commands.
features.enablePersonaSelectorbooleanfalseShow the persona selector in the status bar, allowing you to switch between additional assistant personas.
features.cacheKeepaliveWidgetbooleanfalseShow a status-bar widget that displays cache warmth, a countdown to the next ping, and controls to extend, reduce, or stop the idle ping chain. Requires cache keepalive to be enabled.
💡 Positron users

These settings also exist as Positron VS Code settings (assistant.experimentalFeatures, assistant.devMode, assistant.enablePersonaSelector, and assistant.cacheKeepaliveWidget). They are not exposed in the Settings UI — edit settings.json directly. When set in both places, Positron merges them; see Positron Settings for priority order.

Administrator-Managed Settings

In a managed deployment — Posit Workbench, Posit Connect, or any launcher that controls the session’s environment — an administrator can supply settings through two environment variables. These work on every platform: Positron, RStudio, Standalone, Desktop, Canvas, and the terminal.

📝 Policy, not a security boundary

These controls are best-effort administrative policy, not a security boundary. A user who controls their own environment (or holds a valid API key) can reach a provider or an MCP server directly, whatever these variables say. The tamper-resistance of the delivery path — getting the environment into a session the user can’t edit — is the managed launcher’s job (for example Posit Workbench’s managed session environment), not Posit Assistant’s.

KeyTypeDefaultDescription
POSIT_ASSISTANT_SETTINGS_ENFORCEDJSONA sealed top layer. It beats the global and project settings files, other environment variables, and CLI flags. Users cannot override it.
POSIT_ASSISTANT_SETTINGS_DEFAULTJSONA bottom layer, just above the built-in defaults. It changes what Posit Assistant does out of the box; any value a user sets overrides it.

Both variables carry a JSON object written in the same vocabulary as settings.json — there is no separate policy format. Only the keys the object actually contains are affected; omitting a key leaves it entirely to the layers below.

export POSIT_ASSISTANT_SETTINGS_ENFORCED='{
  "approvalMode": "normal",
  "permission": { "bash": { "curl *": "deny" } },
  "plugins": {
    "strictKnownMarketplaces": [{ "source": "github", "github": "acme/plugins" }]
  }
}'

Resolution Order

With both variables set, settings resolve in this order (last wins):

  1. Built-in defaults
  2. POSIT_ASSISTANT_SETTINGS_DEFAULT
  3. Global ~/.posit/assistant/settings.json
  4. Project .posit/assistant/settings.json
  5. Environment variables
  6. CLI flags
  7. POSIT_ASSISTANT_SETTINGS_ENFORCED

Objects merge key by key, so an enforced "features": { "showTips": false } pins just that one setting and leaves the rest of the features block to the layers below. Arrays and plain values replace whatever is below them.

📝 Positron interleaves differently

In Positron these two layers bracket Positron’s own settings rather than sitting above and below a single file. See Positron Settings.

Format Rules

  • Strict JSON — no comments and no trailing commas, unlike the settings file itself.
  • Read once, at startup. Changing either variable requires restarting the session.
  • These keys are rejected, with an error naming the key: server and workspace.path (owned by whatever launches the session), hooks (the hook event map is not supported through this channel — the useHooks toggle is), and the legacy providers key. Everything else in the settings vocabulary is accepted, including permission, approvalMode, mcpServers, mcp, useHooks, skills, sandbox, storage, logging, workspace.allowedRoots, the features block, and the plugin keys.
  • Problems are reported once at startup. An invalid value drops just that key; an unparseable payload, or one containing an unsafe object key, is ignored entirely. Both show an error message naming the environment variable. A key this version doesn’t recognize is only logged, so a payload written for a newer release doesn’t raise an error for users on an older one.
  • Provider connection settings are not part of this payload: they live in ~/.posit/ai/providers.json (see Provider Settings) and have their own pair of administrator variables, POSIT_AI_PROVIDERS_ENFORCED and POSIT_AI_PROVIDERS_DEFAULT, which work the same way for that file.

Keys With Extra Meaning

Most keys simply win or lose by layer. Four behave in ways worth knowing:

  • approvalMode — an enforced value is a maximum, not a fixed setting, ordered restrictednormalautoyolo. Users can still choose a stricter mode, capped modes are disabled in the mode picker, and /auto / /yolo are hidden above the cap. A user’s saved preference is never overwritten — raising the cap later restores it. A default approvalMode only sets the starting mode for someone who has never chosen one.
  • permission — see Permissions & Trust for what enforced deny and ask rules mean in practice.
  • mcpServers — merged by server name, so an enforced entry pins one server (including "enabled": false as a non-removable off switch) and leaves the rest configurable. Administrator-supplied servers start in every workspace, including untrusted ones, because they come from the launch environment rather than from project files. Pinning named servers cannot stop a user adding a new name — for that, use mcp below.
  • mcp — the MCP admission policy (access plus allow/deny matchers; see MCP Servers). Unlike ordinary keys it never merges across layers: deny lists union, allow lists intersect, and access narrows — an enforced value is a ceiling that can only restrict. A malformed mcp value in an administrator payload fails closed (the layer reads as "access": "none") with an error, instead of silently dropping the restriction.
  • useHooks — which lifecycle hooks may run: "all", "global" (global hooks only, never project hooks, on any workspace), or "none". true/false work as aliases for "all"/"none". Same ceiling/narrowing semantics as mcp, and the same fail-closed behavior on a malformed value. See Hooks.
  • Plugin keys — an enforced enabledPlugins entry cannot be toggled back, and enforced extraKnownMarketplaces entries appear as managed and cannot be removed.

Writing an enforced key into your own settings.json succeeds as a file edit but has no effect on what Posit Assistant uses.

Environment Variables

Some settings can also be controlled via environment variables. Environment variables take precedence over file-based configuration, but not over POSIT_ASSISTANT_SETTINGS_ENFORCED. See Providers for the full list of provider environment variables.