Managed settings
Managed settings (also called organization policy) are settings an administrator sets for every person on a machine. They sit above user and project settings, and a few keys only count when they come from here. Use them to enforce permission rules, approve MCP servers and plugins, pin models, and keep everyone on a supported version.
For the bigger picture of a team rollout, start with Admin setup.
Ways to deliver a policy
| Mechanism | Where it lives | Notes |
|---|---|---|
| Policy file | settings.policy.json in a system folder (table below) | Works on every system. Push it with whatever tool you already use for config files. |
| Drop-in files | settings.policy.d/*.json next to the policy file | Lets several teams each own one file. |
| macOS configuration profile | Preference domain ai.syntic.code (read from /Library/Managed Preferences/ai.syntic.code.plist) | For Macs enrolled in device management. The profile holds the same keys as a policy file. |
| The Syntic service | Fetched at start and cached per user | No device access needed. See Settings from the service. |
Policy file locations
| System | Folder |
|---|---|
| Linux | /etc/syntic/ |
| macOS | /etc/syntic/ and /Library/Application Support/Syntic/ (the second one wins where both set a key) |
| Windows | %ProgramData%\Syntic\ |
| Linux under WSL | /etc/syntic/, then the Windows machine’s C:\ProgramData\Syntic\ as WSL mounts it (the Windows file wins) |
Each folder may hold settings.policy.json and a settings.policy.d/ folder. Policy is read only from these admin locations. A settings.policy.json inside a project folder is ignored, so a cloned repository cannot pose as your policy.
Split a policy across teams
Drop-in files in settings.policy.d/ are applied on top of the base file in alphabetical order, so a later name wins on a conflicting value. Lists such as permission rules are joined rather than replaced. A simple naming scheme keeps the order obvious:
/etc/syntic/
├── settings.policy.json # security team: the baseline
└── settings.policy.d/
├── 10-models.json # platform team: model choices
├── 20-mcp.json # tooling team: approved MCP servers
└── 90-announcements.json # internal comms: start-up messagesHow the sources combine
Managed sources are stacked in this order, each one overriding the one before:
- Policy files (base, then drop-ins; on macOS,
/etc/synticfirst, then/Library/Application Support/Syntic) - Settings delivered by the Syntic service
- The macOS configuration profile
The combined policy then sits on top of everything a user controls. Overall, settings are read in this order, later winning: user file, project file, local file, SYNTIC_SETTING_* environment variables, managed policy. Command-line flags for a single run still apply, but they cannot loosen a managed permission rule, re-enable a mode you switched off, or start a version outside your range.
Switches that only tighten
A few switches can be turned on by any settings file, including a user’s own, and once one file turns them on nothing turns them off again:
| Switch | Effect |
|---|---|
permissions.disableBypassPermissionsMode | Bypass mode cannot be entered. |
permissions.disableAutoMode | Auto mode cannot be entered. |
permissions.blockReadsOutsideWorkingDirectories | File tools may not read outside the working folders. |
Deny rules work the same way: a deny rule from any source is kept, and no allow rule overrides it.
A program that embeds Syntic Code
A program that runs the CLI for its own users can pass managed settings in the SYNTIC_SDK_MANAGED_SETTINGS environment variable, as a JSON object. What happens to them depends on your policy:
| Your policy | Result |
|---|---|
| No admin policy on the machine | The embedding program’s settings apply as policy. |
| Admin policy present (default) | Your policy applies and the embedding program’s settings are ignored. |
Admin policy with "parentSettingsBehavior": "merge" | The embedding program’s settings apply first, and your policy is layered on top. |
Check that a policy is in force
Run syntic doctor on the machine. The report ends with the managed keys it found:
Managed policy
minimumVersion = 0.1.0
blockedMarketplaces = 2 entries
sandbox.bwrapPath = /opt/bwrapManaged policy: none means no source reached the machine. The same report lists settings entries that had to be dropped (for example a value of the wrong type) and allow rules that can never take effect.
When a policy file is broken
A policy file, drop-in or configuration profile that exists but cannot be read stops Syntic Code before a session starts:
Your organization's managed settings could not be loaded, so Syntic will not start:
/etc/syntic/settings.policy.d/20-mcp.json: expected `,` or `}` at line 4 column 3
Ask your administrator to fix the file.This is on purpose. A typo should never quietly drop your rules. Validate files with a JSON checker before you push them.
An example policy
{
"model": "Syntic Code",
"availableModels": ["Syntic Code", "Syntic Code Fast"],
"permissions": {
"deny": ["Read(.env)", "Read(*.pem)", "WebFetch(domain:pastebin.com)"],
"disableBypassPermissionsMode": "disable"
},
"allowedMcpServers": [{ "serverUrl": "https://mcp.example.com/*" }],
"strictKnownMarketplaces": [{ "pathPattern": "^example-org/" }],
"minimumVersion": "0.1.0",
"companyAnnouncements": ["Remember: no customer data in prompts."]
}Permissions
| Key | Effect |
|---|---|
permissions.allow / ask / deny | Rules added for every user. Policy deny rules cannot be overridden. |
allowManagedPermissionRulesOnly: true | Only the policy’s allow rules count. Users’ allow rules, --allowedTools, and “don’t ask again” answers are ignored. Their deny and ask rules still apply, because those only make a session stricter. Counts only in managed policy. |
permissions.disableBypassPermissionsMode | Bypass mode cannot be used. |
permissions.disableAutoMode | Auto mode cannot be used. |
permissions.blockReadsOutsideWorkingDirectories | File reads stay inside the working folders. |
autoMode | Auto mode rule lists and reviewer switches. See Configure auto mode. |
sandbox | Shell sandbox settings, including network.allowManagedDomainsOnly, filesystem.allowManagedReadPathsOnly and bwrapPath (Linux). See Shell sandbox. |
Rules and modes are explained in Permission rules and Permission modes.
Hooks
| Key | Effect |
|---|---|
hooks | Hooks that run for every user. |
disableAllHooks: true | In policy: no hooks run at all, including the policy’s own. |
allowManagedHooksOnly: true | Only the policy’s hooks run. |
allowedHttpHookUrls | The only URLs http hooks may call (* matches any run of characters; an empty list blocks them all). |
See Hooks.
MCP servers
mcpServers, allowedMcpServers and deniedMcpServers control which tool servers people can use. The allow list only counts in managed policy. Matching rules, examples and what users see are on Managed MCP servers.
MCP channels (servers that push messages into a session) have their own switches: "channelsEnabled": false in policy turns them off, and allowedChannelServers narrows which servers may push.
Plugins and marketplaces
| Key | Effect |
|---|---|
enabledPlugins | {"plugin@marketplace": false} forces a plugin off: it cannot be installed, enabled or loaded. |
strictKnownMarketplaces (or allowedMarketplaces) | When present, only these marketplaces may be used. An empty list allows none. |
blockedMarketplaces | Marketplaces that are always refused, even when written another way (for example as a git URL). |
pluginTrustMessage | A note shown whenever a plugin is installed. |
extraKnownMarketplaces | Marketplaces offered to everyone. |
Marketplace entries are sources (owner/repo, git or https URLs, paths) or { "hostPattern": "<regex>" } / { "pathPattern": "<regex>" }. The check runs before anything is fetched. More on Plugins for your organization.
Models and sign-in
| Key | Effect |
|---|---|
model, smallModel, fallbackModel | Defaults for everyone. |
availableModels, deniedModels | Which models can be chosen (name patterns, * allowed). |
modelPicker | The order and labels in /model. |
maxEffortLevel | The highest reasoning effort allowed, overall or per model. |
forceLoginOrgUUID | Accept sign-ins to this organization only. Counts only in managed policy. |
forceLoginMethod | Pins the sign-in method. Syntic Code has a single method today (browser sign-in), so every value, including the older console, leads to that sign-in. It is read from the policy files and the user’s own settings file, never from a project, and syntic doctor lists it when set. |
modelPricing | Your organization’s rates, used for cost figures. |
Versions and updates
| Key | Effect |
|---|---|
minimumVersion / maximumVersion | A build outside the range does not start a session. It prints why and exits with status 4. syntic update and other subcommands still run, so people can always get back into range. |
Unlike the update check, no environment variable skips this gate. When several sources set a bound, the last one in the stacking order wins.
Run everything through a launcher
{ "processWrapper": "/opt/corp/bin/launch --audit" }processWrapper (a string, or a list such as ["/opt/corp/bin/launch", "--audit"]) makes every shell command, hook and MCP server that Syntic Code starts go through your launcher. Use it for auditing or to apply your own process controls. The launcher must be an absolute path. It is read from managed policy only; user and project settings cannot set or clear it.
Messages to users
| Key | Effect |
|---|---|
companyAnnouncements | Messages shown at session start, one per day in turn. |
spinnerTipsOverride | Your organization’s tips next to the spinner (excludeDefault: true hides the built-in ones). |
Messages between sessions
| Key | Effect |
|---|---|
crossSessionInbound | ask, auto or refuse for messages sent from a user’s other sessions. A policy value wins over the user’s. An invalid policy value refuses all such messages until fixed. |
dialogExpiry | Seconds before a waiting message is dismissed. |
Skills
Put skills every user should have in /etc/syntic/skills (Linux), /Library/Application Support/Syntic/skills (macOS) or %ProgramData%\Syntic\skills (Windows), or point SYNTIC_MANAGED_SKILLS_DIR at a folder. skillOverrides in policy can hide or limit any skill (off, user-invocable-only, name-only).
Memory
An organization SYNTIC.md in a policy folder (for example /etc/syntic/SYNTIC.md) is loaded into every session on the machine, before user and project memory. See Memory.
Keys that only count in managed policy
These keys are ignored, or cannot be loosened, when they appear in a user or project file:
| Key | Purpose |
|---|---|
allowManagedPermissionRulesOnly | Only policy allow rules count. |
allowManagedHooksOnly | Only policy hooks run. |
allowedMcpServers | MCP allow list. |
allowedChannelServers | Channel allow list. |
strictKnownMarketplaces, blockedMarketplaces | Marketplace allow and block lists. |
enabledPlugins set to false | Forced-off plugins. |
pluginTrustMessage | Install note. |
forceLoginOrgUUID | Organization pin. |
minimumVersion, maximumVersion | Version range. |
processWrapper | Launcher for child processes. |
requireRemoteManagedSettings | Refuse to start without fresh service-delivered settings. |
parentSettingsBehavior | How an embedding program’s settings combine with yours. |
modelPricing | Rates for cost figures. |
Turn optional traffic off for everyone
Privacy levels are set with environment variables, not settings keys. To stop the optional background calls (update check, connection warm-up, usage refresh, marketplace refresh) on every machine, set SYNTIC_PRIVACY=essential in the environment you deploy. See Data usage and privacy.
Every key, with its type and default, is listed in the settings reference.