claude-code: register the agent's configuration at three scopes, served as the nox-mesh plugin

Skills, subagents, commands and hooks had no machine-wide place, so they were
copied into homes by hand and drifted. Each is now registered once through the
module's tools, kept in its config state, and written per node: the plugin in
the managed directory, settings and instructions in the managed files, or the
account's own directory, touching only what the module placed. hq ADR 0216.
This commit is contained in:
jochen
2026-10-05 11:57:35 +02:00
parent 170b3296e9
commit dd1035a27d
9 changed files with 1653 additions and 25 deletions
+11 -7
View File
@@ -96,8 +96,10 @@ func jsonFile(v any) string {
}
// Render composes the three files. registered — what was registered through this module and applies
// here — is laid over the servers the operator set in its settings.
func Render(facts Facts, settings Settings, binding *Binding, helperPath string, registered Servers) map[string]string {
// here — is laid over the servers the operator set in its settings; config is the rest of what was
// registered (ADR 0216): its settings laid over the operator's `managed_settings`, its instruction sections
// after the mesh's own text. The plugin itself is Marketplace's, and the home's PlaceHome's.
func Render(facts Facts, settings Settings, binding *Binding, helperPath string, registered Servers, config Config) map[string]string {
servers := map[string]any{}
for _, layer := range []map[string]map[string]any{settings.MCPServers, registered} {
for name, entry := range layer {
@@ -109,14 +111,16 @@ func Render(facts Facts, settings Settings, binding *Binding, helperPath string,
}
servers[meshEntry] = map[string]any{"type": "http", "url": facts.Console}
managed := map[string]any{}
for key, value := range settings.ManagedSettings {
managed[key] = value
}
// The operator's `managed_settings` (ADR 0213), then what was registered for the mesh, then for this node.
managed := mergeSettings(map[string]any{}, settings.ManagedSettings)
managed = mergeSettings(managed, RegisteredSettings(config))
// 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")
for key, value := range MarketplaceKeys() {
managed[key] = value
}
if binding != nil && binding.Kind == "api-key" {
managed["apiKeyHelper"] = helperPath
}
@@ -127,6 +131,6 @@ func Render(facts Facts, settings Settings, binding *Binding, helperPath string,
return map[string]string{
"managed-mcp.json": jsonFile(map[string]any{"mcpServers": servers}),
"managed-settings.json": jsonFile(managed),
"CLAUDE.md": instructionsText(facts.Node, role),
"CLAUDE.md": instructionsText(facts.Node, role) + InstructionSections(config),
}
}