The predecessor's agent module was retired and its six files stayed on both workstations telling every session to use tools that no longer exist. Before a successor module is written, the design needs the decisions it rests on and nothing in the record stated them: - ADR 0169 (reconstructed) records what the controller shipped on 2026-09-27 without a record: the operator account is a node fact stated by the operator, the home is derived unless stated, a resource may be placed under it owned by the account, and a node with no account refuses one. - ADR 0170 generalises to-be 29 §3's found-vs-owned boundary to every directory under a home: the module owns the directory and the files it places, writes into the tool's own files for its few keys, never declares a credential's content, and holds everything else as found — a predecessor's leftovers included, which the operator removes once. - ADR 0171 draws the licence line the operator asked to have drawn rather than assumed: the mesh binds and delivers (to-be 14 and 15 stand), the module alone writes the credential file, refresh stays central (ADR 0050), a switch is the binding changed through a controller seat verb asked for via the console, and the token-carrying shell helper is retired. The controller learns nothing about the agent; that is what "no part" means. To-be 36 is the module's design: the ownership map per path, the fate of the six predecessor files, what the three instruction documents say, the licence tools and skill, the console as a node-scoped provision, the package gap stated honestly, and the order of the build. To-be 14, 29 and 34 carry dated notes; the glossary gains "operator account".
18 KiB
layer, status, code, updated, decisions
| layer | status | code | updated | decisions | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| to-be | designed | 2026-10-02 |
|
36 — The operator's agent on a machine: the claude-code module
The agent a person runs at a terminal, put on the machine by the mesh, instructed by the mesh, pointed at the console, and authenticated with a licence the mesh delivers. It is the first member of the family to-be 29 §2 names — the modules that place files under an operator's home — and the smallest, so it is where the pattern is proven before the shell, the terminal and the desktop follow.
What it replaces: the predecessor's module of the same name, which installed the agent's package and placed five files under the operator's home, and a sibling that placed a sixth. The predecessor is retired; those six files are still on both workstations telling every session to use tools that no longer exist. That is the symptom this design answers, and it answers it by making the files a module's again rather than by editing them.
1. What it is
A module, claude-code, universal tier: assigned to every node a person logs into, which is every node
with an operator account (ADR 0176).
It declares the agent's package, owns the agent's configuration directory under the account's home, and
requires two things: model-access, for the licence
(ADR 0178),
and the console on the same machine, for the tools
(ADR 0152). It names no
node, no path and no login: the account and its home are machine facts, the node's name is a machine
fact, the node's role is a setting on the assignment, and the console's address is what the console
serves.
The controller has no part in it beyond what it has in every module. It resolves the account, the home, the licence and the console's port, and delivers them. It holds nothing about the agent: no file shape, no key name, no path. The one controller change this design asks for is not about the agent at all — the licence commands become verbs on the controller's seat, as the other commands did (ADR 0154).
2. What it owns under the home, and what it leaves alone
Every path the module touches is in one of the four classes
ADR 0177
draws, and the class is visible from the shape the definition declares. The agent's directory is
~/.claude; its own state file is ~/.claude.json beside it.
| path | class | declared as |
|---|---|---|
~/.claude/ |
owned directory | a directory, owner the account, readable by the account alone |
~/.claude/CLAUDE.md |
owned | a file: how a session on this mesh works (§4) |
~/.claude/rules/00-mesh.md |
owned | a file: this node's identity (§4) |
~/.claude/rules/conventions.md |
owned | a file: the rules of the repositories (§4) |
~/.claude/skills/mesh-licence/SKILL.md |
owned | a file: the licence skill (§5) |
~/.claude/settings.json |
written into | the agent's settings; the mesh's key is attribution, and only that (below) |
~/.claude.json |
written into | the agent's own state; the mesh's key is the console's entry under the servers the agent speaks to (§3) |
~/.claude/.credentials.json |
written by the module's process | a delivered secret and a step (§5) |
| everything else | found | nothing — the person's memory, history, projects, local settings, plugins, their own rules and skills |
Which keys of the settings file are the mesh's. A key is the mesh's when it encodes a rule of the
mesh, and the person's when it is a preference. attribution — the trailers the agent adds to commits
and pull requests — encodes the repositories' convention and is the mesh's. The model, the spinner, the
drafts, the automation mode and everything else are the person's, and the predecessor's experience with
the model key is the evidence: a mesh that sets a preference reverts a person's choice on every push. A
preference the operator wants on every machine belongs to the family's dotfiles module, not here.
The agent's own state file is written into for one key. The agent is told about the console as one entry among the servers it speaks to, in the file where it keeps that list. Everything else in that file — the account it is logged in as, its caches, its history of projects — is the agent's, and ADR 0102's rule is exactly what keeps it: the mesh sets one key and gives it back on undeclare.
3. The predecessor's six files
They were placed by a generator that no longer exists; to the mesh they are found. ADR 0177 says what happens to each kind, and this is the list:
| file | fate |
|---|---|
CLAUDE.md, rules/conventions.md |
adopted. The module declares the same paths; the host keeps the found original once and writes the mesh's content (ADR 0102) |
settings.json |
written into. The values the predecessor merged and the person changed since — the model among them — stay; the mesh sets its one key |
rules/00-hal-mesh.md |
removed by the operator, once. Its successor is rules/00-mesh.md; the old name carries the predecessor's and stays otherwise |
skills/hal-switch-license/SKILL.md |
removed by the operator, once. Its successor is skills/mesh-licence/SKILL.md |
skills/cleanup/SKILL.md |
removed by the operator, once. A repository hygiene skill naming the predecessor's forge and repository; not the mesh's |
The module's documentation names the three removals, so a person assigning it on a workstation that carried the predecessor knows the step. On a fresh machine there is nothing to remove.
The console's entry changes name. The agent on both workstations today reaches the console under
an entry named after this installation. A definition names no installation
(ADR 0155), so
the module writes the entry as mesh, and every tool an agent sees is prefixed accordingly. The
hand-made entry is the person's to remove; until they do, the agent sees the mesh's tools twice.
4. What the three documents say
Prose, not a paste — the files are the module's; this is what they are for.
CLAUDE.md — how a session on this mesh works. The console is the only path to the mesh, and its
tools are the vocabulary: the record is asked through the records module's tools, symptom first — the
literal error text before a hypothesis — and that is the search before you dig rule rewritten for a
knowledge base that is now the record itself (ADR 0153);
the mesh is asked and changed through the controller seat's verbs — status, plan, assign, push,
settings, and licence once it exists; the forge through the forge module's tools. The hard rules are the
same rules in new words: a file the mesh manages is changed through the verb that owns it or through
the catalogue, never on disk, and plan says what the mesh would write; a store's database is never
written by hand; main is never pushed; the mesh creates no symlinks and nobody else does either; a
package is declared, not installed by hand. It uses the glossary's words — controller, foundation,
node, seat, console — and none of the predecessor's.
rules/00-mesh.md — who this node is. Two facts and one pointer: the node's name, from the
machine; the node's role, from the assignment's settings on this node; and that the other nodes are
asked of the controller's nodes verb rather than listed here. The predecessor's rule carried a table
of every node with its public domain and role; a table is a copy that drifts, and the live answer is
one tool call away. No address, no public domain.
rules/conventions.md — the rules of the repositories. Concise commit messages in the imperative,
focused on why; a branch, a pull request and a human approval for every merge; test before pushing,
because nodes update unattended; follow the playbooks in the record; shared logic in the SDK; the
module repository's rules on manifests. Nothing that names a tool of the predecessor's.
Where the module gets the name and the role. The name is a machine fact the controller already offers a definition. The role is a value a person chooses per node — the laptop, the home-server — and is an operator value on the assignment's node layer, refused by name when unset (ADR 0155). So assigning the module to a node is two acts: the assignment, and the node's role in its settings.
5. The licence
ADR 0178 decides it; this is the shape.
The consumer is (node, claude-code): the operator's interactive sessions on that machine, under
that account, on one licence at a time. The module requires model-access and is put on a licence like
the consumer module already in the catalogue.
Delivery and the write. The mesh delivers the access token sealed to the machine, as a secret in
the module's own state directory, and the bound facts beside it. A step in the module's own process —
the consumer module's existing write, carried over — reads the secret and writes
~/.claude/.credentials.json: owned by the account, readable by the account alone, atomically,
access-token-only. The step names the secret file as what it reads and runs again when it changes
(ADR 0099), and on a schedule as
a backstop, so a refreshed token reaches the file unasked. It runs in the module's own context and
never as the person.
Refresh is the manager module's on the control node, as ADR 0050 built it. It is assigned to nothing today and is the first prerequisite of the build.
The two tools the module serves, listed by the console under the module's name:
| tool | answers |
|---|---|
licence_status |
which licence this machine's agent holds, from the bound facts; when its access token expires; whether the file on disk matches what was delivered — by fingerprint, never by value |
licence_switch |
asks the controller seat's licence verb to put this consumer on the named licence, waits until the credentials file carries the new licence's token, and answers with the licence's name and expiry. Refuses with the mesh's own words when the licence does not exist or the consumer cannot be put on it |
Neither tool, nor the module's log, nor any event it emits, ever carries a token. The module declares
that it invokes the controller seat's licence verb, and nothing else.
The skill — skills/mesh-licence/SKILL.md — wraps licence_switch so a person asks in a sentence,
and carries the predecessor's rules unchanged in substance: never ask for or print a token; never edit
the credentials file by hand; the tool writes the file and the record together; with no licence named,
ask rather than guess.
Enrolling an account happens on the manager node: a licence added by name, its grant obtained by a login in a throwaway home and adopted sealed to that node's key, as the manager module does. The shell helper that ran the agent with a token from a plaintext file is retired and not replaced (ADR 0178 says why).
6. The console
The agent reaches the mesh through the console on the machine's loopback (to-be 34). The module must tell the agent the console's address, and the port is the console's to say: today the console's manifest declares it and the host assigns it, and nothing but the console knows what was assigned. So the console provides a node-scoped provision — the MCP endpoint on loopback — serving its port, and the module requires it. A requirement names what the consumer is coupled to (ADR 0027): the agent is coupled to an MCP endpoint on its own machine, not to a module name. Co-location resolves it, and a machine without the console refuses the agent module by name — which is right, because an agent without the console is the predecessor's situation again.
This is a change to the console's definition, not to the controller. To-be 34 §1 says the console has no provision; this is the one it gains, at node scope, and the design is amended in the same change.
7. Scope, settings and the order of assignment
Every node with an operator account. None has one today; the operator states them first. A node with no account refuses the module, naming the fact.
Per node: the role, in the module's settings on the node layer. Per mesh: nothing.
Order: the manager on the control node and a refresh observed; the licences the operator uses, enrolled; the console's provision and the module in the catalogue; one workstation assigned, the three predecessor files removed there, and a new session read to confirm it sees the mesh's instructions and the console's tools; then the rest.
8. The package
The module declares the agent's package. The distribution every node of the live mesh runs does not carry it in its repositories: the two workstations have it from a build the predecessor's helper made from the community repository, and nothing updates it since the predecessor retired. On those two the declaration is satisfied — the package is present. On a fresh machine the host's package manager refuses it, in its own words, and the module is not applied there. That is correct and is a gap.
The answer the mesh already has a shape for is a package repository for this ecosystem as a seat
(ADR 0109), fed by the
builder with a package it builds from the vendor's release, and trusted by every node's package manager.
Then package: claude-code is answered the way every package is, and updates arrive the way every
update does. It is not built, and it is not this module's to build: it is a seat and a provider module
of its own, needed by every package the distribution does not carry.
Rejected as the answer: the vendor's own installer, which puts a self-updating binary under the person's home. It is a hand-installed package the mesh cannot see, reproduce or roll back, and it updates itself outside the mesh — the arrangement the manifest rule never install a package by hand exists to end.
How it is checked
| Check | Defends |
|---|---|
| the module's definition names no node, path or login, and declares no secret in a file's content | ADR 0112, ADR 0155, ADR 0178 |
| on a lab machine with an account, a seeded home holding a person's rule file, the predecessor's three leftovers and a settings file with the person's model: after assign, the mesh's files are present and owned by the account, the person's file and model are byte-identical, the leftovers are untouched, the console's entry is set; after unassign, the mesh's files are gone, the two keys are given back, the directory and everything else stand | ADR 0177 |
| on a lab machine with no account, the assignment is refused naming the fact | ADR 0176 |
| the credentials file is owned by the account, readable by it alone, and names no refresh token; a switch through the console changes the licence named in the bound facts and the file's fingerprint; neither the tool's answer nor the module's log holds a token | ADR 0178, ADR 0050 |
| the console's provision resolves by co-location and a machine without the console refuses the module by name | ADR 0027, ADR 0152 |
a new session on the assigned workstation lists the console's tools under the mesh prefix and answers "which node am I" from the identity rule |
the exit of the build |
| the package is reported present on the workstations and refused in the package manager's words on a machine without it | §8, honestly |
What this does not settle
- Several operator accounts on one node. ADR 0176 decides one; the module follows.
- A parallel session under another licence on the same machine. The retired helper allowed it by keeping tokens readable; a clean form needs a second consumer identity (to-be 14's open half).
- The package repository seat. §8 names it and leaves it to its own design.
- The rest of the family — shell, terminal, desktop, user-scoped services — each a module of the same shape, each proving nothing new about ownership and something new about its own tool.
References
- ADR 0176, ADR 0177, ADR 0178 — the three decisions this rests on
- to-be 29 — the family; to-be 14, to-be 15 — the licence and the consumer; to-be 34 — the console
- the predecessor's
claude-codemodule and its sibling's identity rule — what is replaced, read from the workstations on 2026-10-02 - mesh-catalog
modules/anthropic-consumer— the write this module carries over;modules/anthropic-manager— the refresh it depends on