Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 6 additions & 1 deletion scripts/test-user-agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down
8 changes: 8 additions & 0 deletions scripts/user-agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Loading