Files
hq/01-RESEARCH/029-the-agent-configured-through-its-module/03-options.md
T
jochen 65c3315a14 Research 029: the agent's configuration is managed at three scopes
The operator's direction: mesh, node and home. A plugin carries the first
two; the home scope places items the module owns path by path; instructions
follow the same layering.
2026-10-04 17:52:48 +02:00

9.8 KiB

03 — Options

The route is chosen: a plugin the mesh serves. What is left open is where each kind of item goes, how it is registered and kept, and what the module does about what it finds in the homes.

Scopes (the operator's direction, 2026-10-04)

The plugin is not the only place the module manages. The agent's configuration is managed at three scopes, and each item is registered at one of them:

scope where it lands reaches
mesh the mesh's plugin, and the mesh's part of the managed files every machine running the agent, including one that joins later
node the same plugin and managed files, as rendered on that machine one machine, or a list of them
home the operator account's own agent directory on a machine (~/.claude) that account on that machine

Each machine renders its own plugin from the registrations that apply to it, so a node-scoped skill sits in the same mesh plugin as a mesh-scoped one, on that machine only. The home scope places an item where the person's own items live, without the plugin's prefix, as if written there by hand. The difference is that the mesh knows it placed the item and can change or remove it.

Instructions follow the same scopes. The agent reads the managed instruction file first, then the home's instruction file and its rule files, then the project's. These are concatenated, not overridden: a later file does not cancel an earlier one, which is how the contradiction measured in 01 came about.

  • The mesh's piece sits in the managed instruction file and is the same on every machine: how a session on this mesh works, and the conventions.
  • The node's piece sits in the same file, rendered per machine: its role, and instruction sections registered for it.
  • Further customisation per machine sits in the home: a rule file the module places, at the home scope, beside whatever the person writes there by hand.

What the home scope needs from ADR 0182. That ADR already lets the mesh own what it places in a home and hold the rest as found. So the module owns each home item it placed, path by path, recorded in its state. It never writes, renames or removes an item it did not place. A home item with the same name as one the person made is refused at registration, never overwritten.

Where each kind of item goes

02 puts a hard limit on the plugin: it carries skills, subagents, commands, hooks, output styles and language servers, but no settings, no permission rules, no instructions, and no tool server the exclusive managed file does not list. So there are four places, not one:

kind goes to why there
skills, subagents, slash commands, output styles the mesh's plugin the only machine-wide place the vendor has for them
hooks the mesh's plugin, with the scripts beside them a hook's script can live in the plugin and be named through ${CLAUDE_PLUGIN_ROOT}. A hook in the managed settings would need its script placed somewhere else
tool servers the managed tool-server file, as today the exclusive file blocks a plugin's servers
settings and permission rules the managed settings file, beside the mesh's keys (ADR 0213) a plugin's settings are dropped
instructions the managed instruction file, in sections a plugin's instruction file is not loaded

The plugin is reached through two managed keys the module already owns the file for: extraKnownMarketplaces, naming a marketplace directory the module writes, and enabledPlugins, set to true for the mesh's plugin. Neither is the operator's to set. Like the attribution key, they are the mesh's keys and outrank whatever the operator sets.

Option A — one plugin

Everything the mesh serves is in one plugin, mesh, so every invocation reads mesh:<name>. That is simple, and the name says where an item came from.

Option B — a plugin per source

One plugin for what the operator registers, and one for what other modules contribute (below). An item then says in its name whether a person or a module definition put it there. But the operator has two prefixes to remember, and an item has two owners to ask about.

Leaning: A. Where an item came from belongs in the module's list tool, not in the item's name.

Who registers an item

  • The operator, through the module's tools, from any machine, for one, several or all of them. The pattern is the tool-server register tool's, extended to every kind:
    • claude_code_<kind>_list, _register, _unregister for skills, subagents, commands, hooks, output styles and instruction sections;
    • claude_code_settings_get / _set and claude_code_permission_allow / _deny / _ask / _remove for the managed settings.
  • Another module, through the agent's seat (ADR 0210). The forge's module wanting the agent to know how pull requests are made here contributes a skill. It declares the contribution in its definition, and the controller renders it to the agent's holder on each machine where both run. That depends on the agent module holding a seat; today it holds none.

The two meet in the one plugin. A contribution and a registration with the same name are refused at registration, and the list tool shows the owner of each.

Where a registration is kept

The tool-server registrations live in a key-value bucket the module declares (ADR 0201), keyed all.<name> or <node>.<name>. Skills differ: a skill is a folder, and it can carry scripts and reference files beside its main file. Every message on the bus is limited to about a megabyte.

  1. One value per item. The item and its files go in one value, refused above a limit well under the bus's. It is simple, it fits the module's existing state, and every item measured in 01 takes 20 KB or less on disk, the vendor's synced skills aside. But a skill with a large reference file cannot be registered at all.
  2. The bus's object store for files, the bucket for the item. Large files are stored in pieces and the item names them. Nothing in the mesh uses the object store yet, so ADR 0201 would need extending.
  3. A repository on the forge. The plugin is built from a repository, and registering an item is a commit. This is reviewable and versioned. But a register tool would have to write to the forge, and the forge would sit on the path to every machine.

Leaning: 1 now, with the limit stated and checked at registration. 2 when an item outgrows it. 3 mixes the operator's configuration into the code review cycle, which it does not need.

Where the plugin is written

The module owns the managed directory, so the marketplace goes under it, written whole by the module's code:

  • the marketplace file;
  • one plugin directory beside it.

It is loaded in place, so a change takes effect at the next session, or at /reload-plugins in a running one. Nothing is copied into the home.

What the module does about what it did not place

01 found stale predecessor files on every machine. The module did not place those, so they are held as found (ADR 0182). It can:

  • report them: a status tool lists the home's skills, subagents, commands and rule files, says which the mesh placed, and names those that duplicate a mesh item or call tools no longer served;
  • import one on request: claude_code_<kind>_import takes an item from one machine's home and registers it at a scope the operator chooses. A skill written by hand on one workstation becomes a mesh, node or home item in one call. Removing the original stays the person's act.

strictPluginOnlyCustomization would make home items stop loading altogether, and home-scoped items with them. That is the operator's choice to make through the managed settings, not a default of the module.

What to confirm first, on one workstation

  1. A directory marketplace named in the managed settings, with its plugin enabled there, loads with no prompt, in place, in an interactive session and in a non-interactive one.
  2. The plugin's skills, subagents and commands are offered under mesh:, beside the home's own items, with no collision.
  3. A hook in the plugin runs, with its script found through ${CLAUDE_PLUGIN_ROOT}.
  4. The exclusive tool-server file still loads the console, and a server in the plugin does not load, as documented.
  5. autoMode in the managed settings changes what the agent refuses (ADR 0213's open point).
  6. The account can read the marketplace in the managed directory, which root owns.
  7. The managed instruction file and a home rule file the module placed are both loaded, in that order.

Questions a decision has to answer

  • One plugin or one per source (leaning: one).
  • How a registration is kept, and the size limit (leaning: one value per item, with a stated limit).
  • Whether the managed settings are set through tools writing the module's state, or through the controller's settings layer as ADR 0213 has it. If both, which one wins on the same key.
  • Whether the agent module holds a seat, so that other modules can contribute to it.
  • The three scopes, and the home scope's ownership rule: the module owns exactly the home paths it placed, recorded in its state, and refuses a name the person already uses.
  • Whether settings take the same three scopes. The home's settings file is the person's own, so it is left out unless the operator chooses otherwise.