feat(db): move container config from filesystem to DB#2351
Merged
Conversation
Source of truth for container runtime config moves from
groups/<folder>/container.json to a new container_configs table.
The file becomes a materialized view written at spawn time.
- New container_configs table with scalar columns (provider, model,
effort, image_tag, assistant_name, max_messages_per_prompt) and
JSON columns (mcp_servers, packages_apt, packages_npm, skills,
additional_mounts)
- Startup backfill seeds DB from existing container.json files
- materializeContainerJson() replaces readContainerConfig + ensureRuntimeFields
- Self-mod handlers (install_packages, add_mcp_server) write to DB
- Provider cascade simplified: session -> container_configs -> 'claude'
- ncl groups config-{get,update,add-mcp-server,remove-mcp-server,
add-package,remove-package} custom operations
- restartAgentGroupContainers() helper for config change propagation
- Container side unchanged (still reads /workspace/agent/container.json)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
703e49a to
31ccc61
Compare
|
Docs PR opened: glifocat/nanoclaw-docs#286 Updated nine docs pages to reflect the move of container config from |
- config-add/remove-package now rebuild image + restart containers - Deduplicate packages in self-mod install_packages handler - Add runtime whitelist guards for SQL column interpolation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced May 9, 2026
`ncl groups config get` now works alongside `ncl groups config-get`. Parser joins all positionals with dashes; dispatcher falls back by trimming the last segment as a target ID (`ncl groups get abc123`). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Operation keys like 'config get' read naturally and crud.ts normalizes spaces to dashes for the registry name. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
de191b3 to
37b5496
Compare
Provider is now managed via `ncl groups config update --provider`. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
config add/remove-package should only update the DB and restart. Image rebuild is handled by the self-mod approval flow or manually. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8c38c1e to
08698da
Compare
Decouple container restart from config updates — config CLI ops now only write to the DB; restart is a separate `ncl groups restart` command with --rebuild and --message flags. Add on_wake column to messages_in so wake messages are only picked up by a fresh container's first poll, preventing dying containers from stealing them during the SIGTERM grace window. killContainer accepts an onExit callback for race-free respawn. Agent- called restart auto-scopes to the calling session. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add cli_scope column to container_configs with three levels: - disabled: agent never learns about ncl (instructions excluded from CLAUDE.md) and host dispatch rejects any cli_request - group (default): agent can only access groups, sessions, destinations, and members resources, scoped to its own agent group with auto-filled --id/--agent_group_id/--group args. Help output reflects the scope. - global: unrestricted access (current behavior) Enforcement is host-side only — no image rebuild or env var needed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When init-first-agent creates an agent group for an owner, set cli_scope to 'global' so the owner's personal agent has full ncl access. All other agent groups remain 'group'-scoped by default. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Group-scoped agents could previously: - See all agent groups via `groups list` (generic list skips --id filter) - Look up any session by UUID via `sessions get` - Request cli_scope change to global via config update approval Fixed by: - Post-handler filtering: list results filtered, get results verified against caller's agent_group_id - Pre-handler --id check scoped to resources where id IS the group ID (groups, destinations) so session UUIDs aren't falsely rejected - cli_scope/cli-scope args blocked outright for group-scoped agents, before the approval gate Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CLAUDE.md: new key files, updated groups verbs, rewritten self-mod section, new Container Config and Container Restart sections - db-central.md: container_configs table (§1.15), migrations 014+015 - db-session.md: messages_in schema with trigger, source_session_id, on_wake columns - schema.ts: comment no longer references disk-based config - cli.instructions.md: rewritten for scope-aware usage, auto-fill, restart/config ops, group-scoped examples Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced May 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
groups/<folder>/container.jsonto a newcontainer_configstable in the central DBmodelandeffortas first-class DB columns, ready for PRs feat(container-config): add per-group model + effort overrides #2233 / fix(claude-provider): use [1m] model tag for reliable 1M context #2280 to wire into the container runner without conflictWhat changed
container_configstable with scalar columns (provider,model,effort,image_tag,assistant_name,max_messages_per_prompt) and JSON columns (mcp_servers,packages_apt,packages_npm,skills,additional_mounts)container.jsonfiles on first run (idempotent)materializeContainerJson()replacesreadContainerConfig+ensureRuntimeFields— reads DB, writes file at spawn timeinstall_packages,add_mcp_server) write to DB instead of filesession → agent_groups.agent_provider → container.json → claude) to 2-step (session → container_configs.provider → claude)ncl groups config-*custom operations:config-get,config-update,config-add-mcp-server,config-remove-mcp-server,config-add-package,config-remove-packagerestartAgentGroupContainers()helper extracted for config-change propagationWhy
Container config was split-brained:
providerlived in both the DB and the file with a cascade nobody used, self-mod wrote to the file, ncl wrote to the DB, and skills told users to edit the file directly. Addingmodel/effort(PRs #2233, #2280) would have made this worse. Single source of truth in the DB eliminates the split, makes config queryable (SELECT * FROM container_configs WHERE model = 'claude-opus-4-6'), and gives operatorsnclcommands for all config fields.Test plan
resolveProviderNametests updated for 2-param cascadecontainer.jsonfiles, verify backfill populatescontainer_configsncl groups config-get --id <id>shows correct configncl groups config-update --id <id> --model claude-sonnet-4-6restarts containerinstall_packages/add_mcp_serverapproval flow writes to DB🤖 Generated with Claude Code