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
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
- macOS / Linux:
-
Project config overrides global settings for a specific project. Place a
.posit/assistant/settings.jsonfile 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"
}
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.
| Key | Type | Default | Description |
|---|---|---|---|
modelTiers.low | string[] | { 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.medium | string[] | { 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.high | string[] | { 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.id | string | "claude-sonnet-4-6" | The model to use for conversations. |
model.provider | string | "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.thinkingEffort | string | — | Default thinking effort level for new conversations. During a conversation, thinking effort is adjusted via the UI and stored per-conversation. |
model.webSearch | boolean | false | Default 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"
}
| Key | Type | Default | Description |
|---|---|---|---|
permission | string | object | — | Permission 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. |
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 ..."
}
}
}
}
| Key | Type | Default | Description |
|---|---|---|---|
type | string | "local" | Server type. "local" for stdio subprocess, "remote" for HTTP/SSE. |
command | string[] | — | Command and arguments to start a local MCP server. |
url | string | — | URL of a remote MCP server. |
enabled | boolean | true | Whether this server is active. |
timeout | number | 10000 | Connection timeout in milliseconds. |
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.
| Key | Type | Default | Description |
|---|---|---|---|
skills.paths | string[] | ["~/.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. |
When the same skill name exists in more than one directory, the version from the later directory is used.
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
}
}
| Key | Type | Default | Description |
|---|---|---|---|
extraKnownMarketplaces | object | {} | 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. |
enabledPlugins | object | {} | 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.allowedComponents | string[] | all types | Restrict 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.hostTokens | object | {} | 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.strictKnownMarketplaces | array | — | Marketplace 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.blockedMarketplaces | array | — | Marketplace denylist, using the same matcher entries as strictKnownMarketplaces. A match is blocked regardless of the allowlist. Global scope only. |
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.
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.
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.
| Key | Type | Default | Description |
|---|---|---|---|
runtime.r.enabled | boolean | true | Enable R runtime integration. |
runtime.r.path | string | "Rscript" | Path to the Rscript executable. |
runtime.r.timeout | number | 30000 | Timeout in milliseconds for R code execution. |
runtime.python.enabled | boolean | true | Enable Python runtime integration. |
runtime.python.path | string | "python3" | Path to the Python executable. |
runtime.python.timeout | number | 30000 | Timeout in milliseconds for Python code execution. |
Workspace Settings
| Key | Type | Default | Description |
|---|---|---|---|
workspace.path | string | "" | Working directory. Defaults to the current directory. |
workspace.allowedRoots | string[] | — | 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.
| Key | Type | Default | Description |
|---|---|---|---|
sandbox.enabled | boolean | false | Enable 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.
| Key | Type | Default | Description |
|---|---|---|---|
features.showTips | boolean | true | Show tips above the input after assistant turns and on startup. |
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
}
}
| Key | Type | Default | Description |
|---|---|---|---|
features.autoCompactTokenBuffer | number | 30000 | Tokens 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.
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
}
}
| Key | Type | Default | Description |
|---|---|---|---|
features.cacheKeepalive | boolean | true | Enable cache-keepalive pings after a turn completes for models with a supported cache policy. |
features.cacheKeepaliveMinutes | number | 30 | Maximum 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. |
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.
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
| Key | Type | Default | Description |
|---|---|---|---|
storage.path | string | "~/.posit/assistant" | Directory for conversation storage. |
Logging
| Key | Type | Default | Description |
|---|---|---|---|
logging.level | string | "info" | Log level. Options: "error", "warn", "info", "debug", "trace". |
logging.file | string | "" | Log file path. Defaults to ~/.posit/assistant/logs/{platform}.log. |
logging.console | boolean | true | Output 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"
]
}
}
Some configuration changes require restarting the assistant or opening a new conversation to take effect.
Developer Settings
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
}
}
| Key | Type | Default | Description |
|---|---|---|---|
features.experimentalFeatures | boolean | false | Enable 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.devMode | boolean | false | Enable developer debugging surfaces such as raw tool data display, conversation path copying, and dev-only commands. |
features.enablePersonaSelector | boolean | false | Show the persona selector in the status bar, allowing you to switch between additional assistant personas. |
features.cacheKeepaliveWidget | boolean | false | Show 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. |
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.
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.
| Key | Type | Default | Description |
|---|---|---|---|
POSIT_ASSISTANT_SETTINGS_ENFORCED | JSON | — | A sealed top layer. It beats the global and project settings files, other environment variables, and CLI flags. Users cannot override it. |
POSIT_ASSISTANT_SETTINGS_DEFAULT | JSON | — | A 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):
- Built-in defaults
POSIT_ASSISTANT_SETTINGS_DEFAULT- Global
~/.posit/assistant/settings.json - Project
.posit/assistant/settings.json - Environment variables
- CLI flags
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.
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:
serverandworkspace.path(owned by whatever launches the session),hooks(the hook event map is not supported through this channel — theuseHookstoggle is), and the legacyproviderskey. Everything else in the settings vocabulary is accepted, includingpermission,approvalMode,mcpServers,mcp,useHooks,skills,sandbox,storage,logging,workspace.allowedRoots, thefeaturesblock, 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_ENFORCEDandPOSIT_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, orderedrestricted→normal→auto→yolo. Users can still choose a stricter mode, capped modes are disabled in the mode picker, and/auto//yoloare hidden above the cap. A user’s saved preference is never overwritten — raising the cap later restores it. A defaultapprovalModeonly sets the starting mode for someone who has never chosen one.permission— see Permissions & Trust for what enforceddenyandaskrules mean in practice.mcpServers— merged by server name, so an enforced entry pins one server (including"enabled": falseas 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, usemcpbelow.mcp— the MCP admission policy (accessplusallow/denymatchers; see MCP Servers). Unlike ordinary keys it never merges across layers:denylists union,allowlists intersect, andaccessnarrows — an enforced value is a ceiling that can only restrict. A malformedmcpvalue 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/falsework as aliases for"all"/"none". Same ceiling/narrowing semantics asmcp, and the same fail-closed behavior on a malformed value. See Hooks.- Plugin keys — an enforced
enabledPluginsentry cannot be toggled back, and enforcedextraKnownMarketplacesentries 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.