library(ally)
list_agent_instructions()
#> ── Agent instructions ─────────────────────────────────────────────────
#>
#> ── User (all projects) ──
#>
#> 1: Claude Code ~/.claude/CLAUDE.md 24 lines
#> 2: Posit Assistant ~/.posit/assistant/AGENTS.md not found
#>
#> ── Project (report) ──
#>
#> 3: Codex, Posit Assistant, Claude Code AGENTS.md 12 lines
#> 4: Claude Code CLAUDE.md not foundWhat is an instruction file?
An instruction file is a Markdown file where you tell an AI coding assistant how you like to work: “use the native pipe”, “write tests with testthat”, “never touch the data-raw/ folder”. The assistant reads it at the start of every conversation, so you don’t have to repeat yourself.
Each assistant looks for its own file, in two places:
- In your home folder, for instructions that apply to every project on your computer. This is where personal preferences go.
- In a project, for instructions about that project alone: its structure, its conventions, the packages it uses. These files can be committed to git so collaborators’ assistants follow them too.
The trouble is knowing which file each assistant reads, and where. {ally} shows you, and opens the one you want to edit.
See what you have
list_agent_instructions() shows the instruction files for the assistants on your computer, in your home folder and in the current project:
Each row is one file: who reads it, where it is, and how long it is. Files that don’t exist yet are listed as “not found” so you can see where they would go.
Only assistants installed on your computer appear in the user section. {ally} judges that by whether the assistant’s folder in your home folder (~/.claude, ~/.codex, ~/.posit) exists. Pass scope = "user" or scope = "project" to see just one section.
Listing never creates or changes anything.
Edit one
edit_agent_instructions() shows the same numbered list and opens the file you pick, in Positron or RStudio:
edit_agent_instructions()
#> Which instructions do you want to edit?
#>
#> ── User (all projects) ──
#>
#> 1: Claude Code ~/.claude/CLAUDE.md 24 lines
#> 2: Posit Assistant ~/.posit/assistant/AGENTS.md not found
#>
#> ── Project (report) ──
#>
#> 3: Codex, Posit Assistant, Claude Code AGENTS.md 12 lines
#> 4: Claude Code CLAUDE.md not found
#> Selection (blank to cancel): 1
#> ✔ Opening '~/.claude/CLAUDE.md'To skip the list, name the file by the assistant that reads it: "claude" for Claude Code, "codex" for Codex, "posit" for Posit Assistant, or "agents" for the project’s shared AGENTS.md.
edit_agent_instructions("posit")
edit_agent_instructions("agents")
edit_agent_instructions("claude", scope = "user")Claude Code has a file for you and one for the project, so edit_agent_instructions("claude") asks which one you mean when both exist. Add scope to go straight to one.
If the file doesn’t exist yet, {ally} asks whether to create it, empty, and then opens it. Existing files are only ever opened, never changed.
Which assistant reads which file
| Assistant | Every project | This project |
|---|---|---|
| Claude Code | ~/.claude/CLAUDE.md |
CLAUDE.md, or AGENTS.md when there is no CLAUDE.md
|
| Codex | ~/.codex/AGENTS.md |
AGENTS.md |
| Posit Assistant | ~/.posit/assistant/AGENTS.md |
AGENTS.md |
A few less common files are listed only when they exist:
-
~/.codex/AGENTS.override.md, which Codex reads instead of~/.codex/AGENTS.md. -
.claude/CLAUDE.md, which Claude Code reads like aCLAUDE.mdat the top of the project. -
CLAUDE.local.md, which Claude Code reads for your own notes on a project. It is meant to stay out of git.
One project file for every assistant
AGENTS.md is becoming the shared name for project instructions. Codex, Posit Assistant, Cursor, GitHub Copilot and Gemini CLI all read it, and so does Claude Code (from version 2.1.277), but only when the project has no CLAUDE.md of its own. A project with just an AGENTS.md gives every assistant the same instructions.
If a project has both, Claude Code reads its CLAUDE.md and ignores AGENTS.md, and list_agent_instructions() points that out:
#> ! Claude Code reads 'CLAUDE.md' in this project, not 'AGENTS.md'. To share
#> 'AGENTS.md' with it, add the line `@AGENTS.md` to 'CLAUDE.md'.A line reading @AGENTS.md in a CLAUDE.md pulls the whole AGENTS.md in at that spot, so Claude Code sees both files. Anything only Claude Code should see can stay in CLAUDE.md around that line.
A walkthrough you can run
Everything below runs against a throwaway project, so it touches nothing else on your computer. It looks at the project section only, since the user section would show your own home folder.
library(ally)
project <- fs::dir_create(fs::path(tempdir(), "report"))
withr::with_dir(project, list_agent_instructions(scope = "project"))
#>
#> ── Agent instructions ──────────────────────────────────────────────────────────
#>
#> ── Project (report) ──
#>
#> 1: Codex, Posit Assistant, Claude Code AGENTS.md not found
#> 2: Claude Code CLAUDE.md not foundAdd an AGENTS.md and every assistant reads it, Claude Code included:
writeLines(
c("# Report", "", "Use the native pipe `|>`.", "Write tests with testthat."),
fs::path(project, "AGENTS.md")
)
withr::with_dir(project, list_agent_instructions(scope = "project"))
#>
#> ── Agent instructions ──────────────────────────────────────────────────────────
#>
#> ── Project (report) ──
#>
#> 1: Codex, Posit Assistant, Claude Code AGENTS.md 4 lines
#> 2: Claude Code CLAUDE.md not foundAdd a CLAUDE.md as well and Claude Code switches to it:
writeLines("Keep answers short.", fs::path(project, "CLAUDE.md"))
withr::with_dir(project, list_agent_instructions(scope = "project"))
#>
#> ── Agent instructions ──────────────────────────────────────────────────────────
#>
#> ── Project (report) ──
#>
#> 1: Codex, Posit Assistant AGENTS.md 4 lines
#> 2: Claude Code CLAUDE.md 1 line
#>
#> ! Claude Code reads 'CLAUDE.md' in this project, not 'AGENTS.md'. To share 'AGENTS.md' with it, add the line `@AGENTS.md` to 'CLAUDE.md'.list_agent_instructions() also returns the list as a tibble, invisibly, if you want to work with it in code:
files <- withr::with_dir(project, list_agent_instructions(scope = "project"))
#>
#> ── Agent instructions ──────────────────────────────────────────────────────────
#>
#> ── Project (report) ──
#>
#> 1: Codex, Posit Assistant AGENTS.md 4 lines
#> 2: Claude Code CLAUDE.md 1 line
#>
#> ! Claude Code reads 'CLAUDE.md' in this project, not 'AGENTS.md'. To share 'AGENTS.md' with it, add the line `@AGENTS.md` to 'CLAUDE.md'.
files[, c("read_by", "exists", "lines")]
#> # A tibble: 2 × 3
#> read_by exists lines
#> <chr> <lgl> <int>
#> 1 Codex, Posit Assistant TRUE 4
#> 2 Claude Code TRUE 1