claude-code
User settings, operator-enforced managed settings, and MCP servers for the Claude Code CLI and its editor panels.
Configures Claude Code. Install it with the
claude-code devtool.
toolconfigs:
- id: claude-code
name: claude-code
config:
managedSettings:
permissions:
defaultMode: bypassPermissionsconfig fields
| Field | Type | Description |
|---|---|---|
settings | object | The user settings layer, written to ~/.claude/settings.json and owned by the login user. Unknown keys round-trip untouched. |
managedSettings | object | The managed settings layer, written root-owned to /etc/claude-code/managed-settings.json. Highest precedence; survives user edits. |
mcpServers | object | MCP servers to apply at user scope. See below. |
The two settings layers mirror the soft/hard split Claude Code itself defines: settings
is what a user may override, managedSettings is operator policy — the same file a
corporate device-management policy would target, so the two compose.
Permissions default to bypass
Unless you say otherwise, Ringleader writes
permissions.defaultMode: "bypassPermissions" into the managed layer. A workstation is
the sandbox that Claude Code’s permission prompts exist to protect, so prompting inside
one is friction with no safety gain.
This happens on install alone — a workstation with the claude-code devtool and no
toolconfig still gets it.
Ringleader steps back if you have expressed an opinion. Setting either
permissions.defaultMode or permissions.disableBypassPermissionsMode in
managedSettings leaves your permissions block exactly as written. Any other keys in
that block — allow, deny, ask — are preserved either way.
toolconfigs:
- id: claude-code
name: claude-code
config:
managedSettings:
permissions:
defaultMode: default # opt out of bypass; prompts return
deny:
- "Bash(rm -rf *)"The background auto-updater is off
Also on install alone, Ringleader writes env.DISABLE_AUTOUPDATER: "1" into the
managed layer. Claude Code is installed globally as root and pinned to the version
the recipe resolves, so the updater — which runs as the workstation user — cannot
write that prefix, and would move the workstation off its pinned version if it could. All
it produced was an Auto-update failed warning on the status line.
claude update still works as a manual escape hatch, and the declarative way to
move a workstation is the devtool’s version.
The same operator-wins rule applies: set the key yourself and your value stands.
toolconfigs:
- id: claude-code
name: claude-code
config:
managedSettings:
env:
DISABLE_AUTOUPDATER: "0" # opt back into background auto-updateMCP servers
mcpServers is a map of server name to definition. Ringleader does not write a file
for these: it runs Claude Code’s own claude mcp add --scope user as the login
user, so the servers land where the terminal CLI and the editor panels read them,
and you can still add your own servers by hand.
| Field | Type | Description |
|---|---|---|
type | string | http, sse, or stdio. Defaults to stdio when command is set, otherwise http. |
url | string | Required for http and sse. |
headers | object | Header name to value, for http/sse. May carry secret references. |
command | string | Required for stdio. |
args | array of string | Arguments for stdio. |
env | object | Environment for a stdio server. May carry secret references. |
toolconfigs:
- id: claude-code
name: claude-code
config:
mcpServers:
linear:
type: http
url: https://mcp.linear.app/mcp
github:
type: http
url: https://api.githubcopilot.com/mcp/
headers:
Authorization: "Bearer ${secret:gh-token/token}"Applying them is change-gated. It runs the first time the workstation sets itself up and again only when
the desired server set changes, so tokens you obtained interactively (via /mcp in
Claude) are never disturbed by a routine re-apply. When the set does change, each
declared server is re-added, and any server Ringleader previously managed and you have
since removed from the config is removed from the workstation. Servers you added yourself are
never touched.
An empty mcpServers: {} is a valid declaration: “manage zero servers”, which still
removes the ones Ringleader previously added.
Servers arrive unauthenticated
/mcp in Claude and authenticate in the browser. Pair with
passthrough-www-browser
to have that page open on your laptop.Workspace trust
Folders in sources[].path and trustedFolders are pre-trusted for the CLI, so it
never opens with a trust prompt on the code the workstation exists to work on. Ringleader
merges the trust flags into Claude’s own state file rather than overwriting it, and a
folder that is already trusted is left completely alone.
Example
The full picture — a workstation whose terminal claude and editor panel both open in bypass
mode, with an MCP server wired up:
apiVersion: workstations.ringleader.dev/v1
kind: WorkstationConfig
metadata:
name: ai-box
namespace: local
spec:
selector:
matchLabels:
tier: dev
identity:
user: dev
shell: /bin/bash
devtools:
- name: nodejs
version: "24"
- name: claude-code
- name: vscode-web
- name: passthrough-www-browser
toolconfigs:
- id: claude-code
name: claude-code
config:
mcpServers:
linear:
type: http
url: https://mcp.linear.app/mcp
managedSettings:
permissions:
defaultMode: bypassPermissions
sources:
- name: app
git:
url: https://github.com/acme/app.git
ref: main
path: /home/dev/src/app # pre-trusted
defaultLocalBinding:
enabled: true
autoForward:
forwardAll: true
urlForward:
enabled: true
open: trueNotes
- A
mcpServersentry needs theclaudeCLI on the workstation. Declare theclaude-codedevtool; without it, the apply step fails loudly. - Secret-bearing headers and environment values are passed to Claude through the environment, never written into a script or a diagnostic record.
- Editor panels ignore the CLI’s managed settings. To set panel behaviour, use the
vscode-weborvscode-servertoolconfig.