# claude-code The operator's agent on a machine (novox/hq design 36): its package, its machine-wide managed configuration, and the consumer side of the Anthropic licence manager (design 39, ADR 0183). ## What it owns Two directories, declared, so the mesh refuses a second module owning either: - `/etc/claude-code`, the agent's machine-wide managed directory, root's, `0755`. - `~/.claude` under the operator account's home, the operator's, `0700`. The module owns the directory — that it exists, who owns it, its mode — and of what is inside only what it writes. Everything else in it (memory, history, projects, local settings, a person's own rules and skills) is the person's and is never read or written (hq ADR 0182). Unassigned, the module leaves the directory: the host removes a directory only when it is empty. ## What it writes Under the agent's managed directory, `/etc/claude-code`, owned whole by this module and rewritten whenever the node's tool runtime collects the module's tools: | file | holds | |---|---| | `managed-mcp.json` | the tool servers every session loads: the mesh's console as `mesh`, and the servers set in this module's `mcp_servers` setting. **Exclusive**: a server not listed here does not load — not one added with `claude mcp add`, not a project's `.mcp.json`, not a plugin's | | `managed-settings.json` | the repositories' attribution convention, the claude.ai connectors kept beside the managed servers, and the key-helper while the node holds an API-key licence | | `CLAUDE.md` | how a session on this mesh works, this node's name and role, the conventions | Under the operator's home, only `~/.claude/.credentials.json`, and only when the licence manager hands this node a subscription token. Nothing else under the home is read or written. ## Over NATS Everything between this module and the rest of the mesh is NATS, in three kinds: an **event** says that something happened and carries no secret, because a stream keeps it; a **request** carries a token, because nothing keeps it (hq design 32 §10); and **state** is the current value of something every node must see, a node that joins later included — kept, so it carries no secret either (hq ADR 0201). | what | how | |---|---| | what this node holds | the module's `holdings` state, one key for this node — the account, the kind, fingerprints and expiries, never a token — written at start and whenever the credentials file changes (hq ADR 0206) | | a person ran `/login` here | the credentials file gains a refresh token this module never writes; its next report shows it, and the licence manager asks `claude_code_grant` for it, giving its key — the one time a refresh token leaves the node, for the manager to adopt by refreshing it | | what this node should hold | the licence manager's `bindings` state, this node's key; on a newer generation this module asks `anthropic-licence-manager.current` for its token, sealed to the key it sends, and writes it access-token-only — so the agent here never refreshes. A node that was off reads its key when it is back | | an MCP server registered through this module | a key in the module's `servers` state — `all.` for every node, `.` for one; every node watches it and renders what applies to it, a node's own entry over the one for every node. A node that joins later, or was off, reads the whole current set at start; unregistering is a delete. An entry with a secret in its `env` or `headers` is refused by the runtime | ## Tools `claude_code_status`, `claude_code_render`, `claude_code_pull`, `claude_code_grant` (for the licence manager), `claude_code_mcp_list`, `claude_code_mcp_register` (this node by default; `nodes: "all"` or a list for more — called for this node alone, its answer names the other nodes running claude-code), `claude_code_mcp_unregister`. ## Settings Per node or for the whole mesh, through `mesh-controller.settings module=claude-code`: - `role` — what this node is, in a few words; shown to every session. - `mcp_servers` — extra tool servers, set by the operator for the mesh or a node, beside the ones registered through the tools; keyed by name, in the vendor's `.mcp.json` entry shape (`{"type":"http","url":…}` or `{"type":"stdio","command":…,"args":[…]}`). The name `mesh` is the module's own and cannot be set. Put a person's own servers here, or they stop loading. ## On a machine that carried the predecessor Remove these by hand, once; the mesh removes nothing it did not make (ADR 0182): - `~/.claude/CLAUDE.md` - `~/.claude/rules/00-hal-mesh.md`, `~/.claude/rules/conventions.md` - `~/.claude/skills/cleanup/`, `~/.claude/skills/hal-switch-license/` - the hand-made console entry in `~/.claude.json` under `mcpServers` — it is ignored now anyway ## Escalation Writing `/etc/claude-code` needs root. The runtime runs as the operator account, and the module uses that account's passwordless `sudo`; on a machine without it, `claude_code_render` says so and nothing is written. ## Code Go, one binary (`cmd/claude-code`) the node's runtime launches. Tested with `go test ./...`; the managed instruction file is held to the TypeScript renderer it replaced (`testdata/rendered-by-typescript.json`), and the sealed box is the licence manager's own format.