Let the operator set the agent's managed settings through claude-code

managed-settings.json carried only the mesh's fixed keys, so permissions and
auto-mode rules could only be set by hand per machine, outside the mesh.
A managed_settings setting is laid under the mesh's keys, which still win.
This commit is contained in:
jochen
2026-10-04 17:31:20 +02:00
parent a831087a02
commit 8067e91409
4 changed files with 57 additions and 6 deletions
+15 -4
View File
@@ -10,9 +10,11 @@ package main
// servers the operator declared or registered through this module. Exclusive by
// the vendor's rule — a server not listed here does not load (operator's choice,
// 2026-10-03).
// managed-settings.json the mesh's keys only: the repositories' attribution convention, the claude.ai
// connectors kept beside the managed servers, and — for an API-key licence only —
// the key-helper. A person's preferences are theirs.
// managed-settings.json the keys the operator set in this module's `managed_settings` (the agent's
// permissions and auto mode, say), under the mesh's own keys, which always win:
// the repositories' attribution convention, the claude.ai connectors kept beside
// the managed servers, and — for an API-key licence only — the key-helper. A
// person's preferences are theirs, in their own settings.
// CLAUDE.md how a session on this mesh works, who this node is, the conventions.
import (
@@ -38,6 +40,8 @@ type Facts struct {
type Settings struct {
Role string `json:"role"`
MCPServers map[string]map[string]any `json:"mcp_servers"`
// ManagedSettings are keys of the agent's managed settings the operator sets, for the mesh or a node.
ManagedSettings map[string]any `json:"managed_settings"`
}
// Binding is the licence this node holds, as it was last applied.
@@ -105,7 +109,14 @@ func Render(facts Facts, settings Settings, binding *Binding, helperPath string,
}
servers[meshEntry] = map[string]any{"type": "http", "url": facts.Console}
managed := map[string]any{"attribution": map[string]any{"commit": "", "pr": ""}, "allowAllClaudeAiMcps": true}
managed := map[string]any{}
for key, value := range settings.ManagedSettings {
managed[key] = value
}
// The mesh's own keys are laid last: a setting never replaces them.
managed["attribution"] = map[string]any{"commit": "", "pr": ""}
managed["allowAllClaudeAiMcps"] = true
delete(managed, "apiKeyHelper")
if binding != nil && binding.Kind == "api-key" {
managed["apiKeyHelper"] = helperPath
}