diff --git a/AGENTS.md b/AGENTS.md index 3d56da74..6a28e343 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1167,6 +1167,11 @@ file) and `~/.claude/CLAUDE.md` (a symlink to it), so Codex and Claude Code read - **Create only.** If either path exists (a file, a symlink, a dangling one) the account is left as it is: nothing is overwritten, appended to or re-linked. The file is seeded once, not managed, so editing `scripts/user-agents.md` reaches new accounts only; an existing account is changed by its owner. +- **Personal additions go in `~/.claude/local.md`.** The text ends by importing it (`@~/.claude/local.md`, plus a + sentence telling Codex, which does not follow imports, to read it if it exists), the same name the distributed + accounts use (`agent-local-md.tf`). What one person's account needs (the machines it reaches, its projects, + preferences) goes there, never into this shared text or a repository. An account seeded before the import was + added gets it only by adding those lines itself: the seeder never appends. - **As the account, never as root.** Root only dispatches (`runuser`); the files are created by the account that owns them. - **No box is replaced or rebooted for it.** It is published inside the S3 setup scripts, and every instance diff --git a/scripts/test-user-agents.py b/scripts/test-user-agents.py index cc932901..ac2deed4 100644 --- a/scripts/test-user-agents.py +++ b/scripts/test-user-agents.py @@ -136,7 +136,12 @@ def test_the_file_is_a_title_the_session_values_paragraph_and_the_models_section self.assertTrue(lines[2].endswith("before every push.")) # The owner, 2026-10-10: every account is told which cheaper models exist and when to hand them work. self.assertEqual(lines[4], "## Cheaper models for straightforward work") - self.assertEqual([l for l in lines if l.startswith("#")], [lines[0], lines[4]], "one title, one section") + # The owner, 2026-10-27: every account also imports its own ~/.claude/local.md, the same name the + # distributed accounts use, so what is personal stays out of this shared text. + own = "## This account's own instructions" + self.assertEqual([l for l in lines if l.startswith("#")], [lines[0], lines[4], own], "one title, two sections") + self.assertIn("\n@~/.claude/local.md\n", text) + self.assertIn("Codex does not follow the `@` import above", text) for model in ("`haiku`", "`sonnet`", "Opus 5.5"): self.assertIn(model, text) # Subagents only ever go down a model: a Sonnet session must not start an Opus subagent (owner, 2026-10-10). diff --git a/scripts/user-agents.md b/scripts/user-agents.md index 70ca5312..778d7589 100644 --- a/scripts/user-agents.md +++ b/scripts/user-agents.md @@ -29,3 +29,11 @@ How to use them: - One task per subagent. Check what it did yourself (run the tests, read the diff) before relying on it. - If a subagent gets it wrong once, do that piece in the main session instead; do not retry the same model. - Never hand a cheaper model an action that cannot be undone: a deploy, a delete, a push to main, a credential. + +## This account's own instructions + +@~/.claude/local.md + +Codex does not follow the `@` import above: if `~/.claude/local.md` exists, read it too. It holds this account's own +instructions (the machines it can reach, its projects, what its person prefers), kept out of this shared starter text +and out of every repository.