--- id: docs-conventions/sweep-agents-md-primary-claude-md-pointer title: 'Sweep: AGENTS.md becomes the real instructions everywhere, CLAUDE.md a pointer beside it' theme: docs-conventions status: open created: 2026-08-25 date_source: stated order: 1 --- **AGENTS.md becomes the main instruction file everywhere, with a CLAUDE.md beside it that just references it — not the other way round, which is how it is today.** Wanted 2026-08-25. A full sweep across the platform and every plugin repo. **The root pairing exists already, backwards.** `platform/AGENTS.md` is five lines: _"The instructions live in `CLAUDE.md`. Read it first — this file only points there."_ `CLAUDE.md` is the real, long document. That is the exact inverse of what is wanted, and it is the clearest single example of the sweep: swap which file holds the content and which file points, keep both present so either harness's auto-discovery convention finds the same guidance — which is the reasoning the current file already states, just applied backwards. **Four subdirectory `CLAUDE.md` files carry real, substantial documentation and have no `AGENTS.md` at all** — found 2026-08-25, none of these have a pair to flip, they need one created: `platform/src/apps/CLAUDE.md` (271 lines), `platform/src/databases/CLAUDE.md` (231 lines), `platform/themes/CLAUDE.md` (118 lines), `platform/plugins/CLAUDE.md` (92 lines). **Every plugin repo has NEITHER file — 19 of 19, checked 2026-08-25.** `atelier`, `bitcoin-wallet`, `browser`, `desktop`, `email`, `example`, `gitea`, `invoices`, `iris`, `jellyfin`, `kiosk`, `minesweeper`, `music`, `offscale`, `photos`, `proxy-manager`, `soulseek`, `transcribe`, `transmission`, `vault` — none has a `CLAUDE.md` or an `AGENTS.md`. This is not a swap for plugins, it is adding the convention where it does not exist yet. **`PLUGIN.md`, present in most of them, is a different document and stays untouched** — it is the plugin's own manifest/reference doc (conventions, API surface), not agent guidance; do not conflate the two when sweeping. **Two lookalikes are NOT documentation and are out of scope for this sweep** — converting them would be wrong, not just unnecessary: - **Per-commander `CLAUDE.md` files** (`data/pastilhas@officer.dev/commanders//CLAUDE.md`) are a single commander's own standing brief — operational state for one running agent, not source-tree documentation nobody discovers it by directory convention the way a coding CLI does at a repo root. - **`plugins/proxy-manager/chat/CLAUDE.md`** carries its own warning: _"rewritten from the plugin on every chat that starts here, so an edit would be lost."_ Generated per session, not read by directory convention either — injected directly into that chat's context by the plugin's own code. **Note `atelier-work/` is a separate checkout carrying its own copies of the root, `themes/`, `plugins/`, `src/apps/` and `src/databases/` `CLAUDE.md`/`AGENTS.md` files** — apparently a working clone related to the Atelier extraction. Worth checking whether it is still live before sweeping it twice; if it is a stale branch, the sweep only needs to happen once, in the platform repo. --- **2026-08-25 — the owner points at prior art: `docs/claude-md-touchpoints.md`, an audit written the same day, before any change, exactly so this sweep would not be guessed at.** It replaces the "two lookalikes" section above with something precise: **three writers, one reader**, all named by file and line — 1. `command-hq/directory.ts:653`, `createCommanderDirectory()` — generates a commander's `CLAUDE.md` ONCE, at creation, from `commanderClaudeMd()`. Never rewritten afterward; the commander extends it itself over its own life, which is why this file is correctly excluded from any flip — there is no "primary content" to move, because the content is written by the commander, not shipped as documentation. 2. `api/chat/websocket.ts:237`, `installPluginChatBrief()` — copies a plugin's own `chat/CLAUDE.md` into a plugin-chat's directory, content-diffed so it only rewrites on an actual change. Of 19 plugins, exactly one (`proxy-manager`) ships one. 3. `scripts/backfill-commander-credentials.ts` — a manual, idempotent append pass over EXISTING commander files, marker-guarded so it never duplicates a section. 4. `scripts/docs-check.ts` — read-only, checks `platform/CLAUDE.md` and `officer-dev/CLAUDE.md` (not a plugin's, not a commander's) for numeric drift. This is the one file this sweep must not touch carelessly: whatever ends up as the "pointer" file still has to carry the two numbers `docs:check` parses out of it, or the check needs to move to reading `AGENTS.md` instead. **Confirms the exclusion already written above, with better grounding — do not re-derive it, cite the audit instead.** Commander files and plugin chat briefs are runtime-authored content injected into an agent's cwd, not source-tree documentation a coding CLI discovers by walking up from where it starts. Flipping "which file is primary" has no meaning for a file with no counterpart and no static content to begin with. **Two things the audit surfaces that are genuinely new and unresolved, not covered by "flip the pointer everywhere":** - **The owner's personal `~/.claude/CLAUDE.md` is explicitly, deliberately, never touched by any of this** — the audit's own "Explicitly not written" section: the owner's sessions are un-isolated, `HOME` points at their real home, and a generated file there would land inside the hand-maintained document the owner edits directly (and that a terminal `claude` also reads). **This file is out of scope for the sweep entirely** — it is not a repository doc, it is the owner's own, and it is inherently Claude-specific by its path (`~/.claude/`), not something an `AGENTS.md` convention could apply to. - **A commander's dynamically-generated file is named `CLAUDE.md` specifically, and commanders can run under opencode.** The audit does not ask whether opencode discovers a `CLAUDE.md` in its working directory the way Claude Code does — only Claude/opencode's actual read-side behaviour answers that, and it was out of scope for an audit about WRITING. If opencode does not read `CLAUDE.md` by convention, an opencode-run commander is silently briefed with nothing, which would be a real gap this sweep should catch rather than one it assumes away. Check before deciding whether `commanderClaudeMd()`'s output needs an `AGENTS.md`-named counterpart too.