Add agents-md plugin: auto-load AGENTS.md at session start (#6235)#37241
Add agents-md plugin: auto-load AGENTS.md at session start (#6235)#37241YoshKoz wants to merge 2 commits intoanthropics:mainfrom
Conversation
…8856) The Bash tool appends `pwd -P >| /tmp/claude-<hex>-cwd` to every shell command to capture the resulting working directory, but never deletes the file. On active systems these files accumulate into the thousands and slow down /tmp access (reported in #8856 with 174+ files per 12 h of usage). This plugin registers a Stop hook that deletes all /tmp/claude-*-cwd files owned by the current user when the session ends, providing a clean-up path until the upstream unlinkSync fix lands in the CLI binary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Many AI coding tools (Cursor, OpenAI Codex, Amp) use AGENTS.md as the standard file for project-level agent instructions, while Claude Code natively reads CLAUDE.md. Teams working across tools must currently keep both files in sync or use symlinks (broken on Windows). This plugin registers a SessionStart hook that mirrors Claude Code's own CLAUDE.md discovery logic: it walks up the directory tree from the project root collecting AGENTS.md files, also checks ~/.claude/AGENTS.md for user-level instructions, then injects all content via additionalContext. The lookup priority (user → repo root → subdirectory) matches the existing CLAUDE.md precedence so the two files compose naturally. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds new Claude Code plugins to improve agent-instruction compatibility and to clean up temp cwd-tracking files at session end.
Changes:
- Introduces
agents-mdplugin with aSessionStarthook that discoversAGENTS.mdfiles and injects them viaadditionalContext. - Introduces
tmp-cwd-cleanupplugin with aStophook to remove orphaned/tmp/claude-*-cwdfiles. - Updates the plugin index (
plugins/README.md) with entries for the new plugins.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/agents-md/.claude-plugin/plugin.json | Adds plugin manifest for agents-md. |
| plugins/agents-md/hooks/hooks.json | Registers SessionStart hook for agents-md. |
| plugins/agents-md/hooks/load_agents_md.py | Implements AGENTS.md discovery + context injection. |
| plugins/agents-md/README.md | Documents installation/behavior of agents-md. |
| plugins/tmp-cwd-cleanup/.claude-plugin/plugin.json | Adds plugin manifest for tmp-cwd-cleanup. |
| plugins/tmp-cwd-cleanup/hooks/hooks.json | Registers Stop hook for temp file cleanup. |
| plugins/tmp-cwd-cleanup/hooks/cleanup_cwd_files.py | Implements deletion of orphaned /tmp/claude-*-cwd files. |
| plugins/tmp-cwd-cleanup/README.md | Documents installation/behavior of tmp-cwd-cleanup. |
| plugins/README.md | Adds both plugins to the plugins table. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| | Event | Matcher | Effect | | ||
| |-------|---------|--------| | ||
| | `Stop` | _(all)_ | Deletes `/tmp/claude-*-cwd` files owned by current user | |
There was a problem hiding this comment.
The markdown table in the Hook section starts with || ..., which renders as an extra empty column in most Markdown parsers. Other plugin READMEs in this repo use single leading pipes for tables (e.g., plugins/hookify/README.md). Consider switching to | Event | ... | formatting so the table renders correctly.
| | [pr-review-toolkit](./pr-review-toolkit/) | Comprehensive PR review agents specializing in comments, tests, error handling, type design, code quality, and code simplification | **Command:** `/pr-review-toolkit:review-pr` - Run with optional review aspects (comments, tests, errors, types, code, simplify, all)<br>**Agents:** `comment-analyzer`, `pr-test-analyzer`, `silent-failure-hunter`, `type-design-analyzer`, `code-reviewer`, `code-simplifier` | | ||
| | [ralph-wiggum](./ralph-wiggum/) | Interactive self-referential AI loops for iterative development. Claude works on the same task repeatedly until completion | **Commands:** `/ralph-loop`, `/cancel-ralph` - Start/stop autonomous iteration loops<br>**Hook:** Stop - Intercepts exit attempts to continue iteration | | ||
| | [security-guidance](./security-guidance/) | Security reminder hook that warns about potential security issues when editing files | **Hook:** PreToolUse - Monitors 9 security patterns including command injection, XSS, eval usage, dangerous HTML, pickle deserialization, and os.system calls | | ||
| | [tmp-cwd-cleanup](./tmp-cwd-cleanup/) | Cleans up orphaned `/tmp/claude-*-cwd` files on session exit, working around a Bash tool memory leak ([#8856](https://github.com/anthropics/claude-code/issues/8856)) | **Hook:** Stop - Deletes accumulated working-directory tracking files owned by the current user | |
There was a problem hiding this comment.
This entry describes the underlying issue as a "memory leak", but the plugin behavior and README describe a /tmp file accumulation problem. Consider adjusting the wording here as well to avoid misleading users.
| | [tmp-cwd-cleanup](./tmp-cwd-cleanup/) | Cleans up orphaned `/tmp/claude-*-cwd` files on session exit, working around a Bash tool memory leak ([#8856](https://github.com/anthropics/claude-code/issues/8856)) | **Hook:** Stop - Deletes accumulated working-directory tracking files owned by the current user | | |
| | [tmp-cwd-cleanup](./tmp-cwd-cleanup/) | Cleans up orphaned `/tmp/claude-*-cwd` files on session exit, working around a Bash tool `/tmp` file accumulation issue ([#8856](https://github.com/anthropics/claude-code/issues/8856)) | **Hook:** Stop - Deletes accumulated working-directory tracking files owned by the current user | |
| sections.append( | ||
| f"<!-- AGENTS.md: {path} -->\n{content}" |
There was a problem hiding this comment.
The injected marker includes the full path (<!-- AGENTS.md: {path} -->), which will be an absolute path for ~/.claude/AGENTS.md and can leak the local username/home directory into the model context. Consider emitting only path.name or a redacted label like user-level / repo-root to preserve privacy.
| sections.append( | |
| f"<!-- AGENTS.md: {path} -->\n{content}" | |
| marker_source = "user-level" if path == user_file else "repo-root" | |
| sections.append( | |
| f"<!-- AGENTS.md: {marker_source} -->\n{content}" |
| "name": "Claude Code Community", | ||
| "email": "" | ||
| } | ||
| } |
There was a problem hiding this comment.
author.email is present but set to an empty string. Elsewhere in this repo, plugin manifests either provide a real email (e.g., plugins/security-guidance/.claude-plugin/plugin.json:5-8, plugins/hookify/.claude-plugin/plugin.json:5-8) or omit optional fields. Consider removing the email field when unknown to avoid publishing empty contact metadata.
| "name": "Claude Code Community", | |
| "email": "" | |
| } | |
| } | |
| "name": "Claude Code Community" | |
| } | |
| } |
| | [ralph-wiggum](./ralph-wiggum/) | Interactive self-referential AI loops for iterative development. Claude works on the same task repeatedly until completion | **Commands:** `/ralph-loop`, `/cancel-ralph` - Start/stop autonomous iteration loops<br>**Hook:** Stop - Intercepts exit attempts to continue iteration | | ||
| | [security-guidance](./security-guidance/) | Security reminder hook that warns about potential security issues when editing files | **Hook:** PreToolUse - Monitors 9 security patterns including command injection, XSS, eval usage, dangerous HTML, pickle deserialization, and os.system calls | | ||
| | [tmp-cwd-cleanup](./tmp-cwd-cleanup/) | Cleans up orphaned `/tmp/claude-*-cwd` files on session exit, working around a Bash tool memory leak ([#8856](https://github.com/anthropics/claude-code/issues/8856)) | **Hook:** Stop - Deletes accumulated working-directory tracking files owned by the current user | |
There was a problem hiding this comment.
PR title/description focus on adding the agents-md plugin, but this change also adds a new tmp-cwd-cleanup plugin entry. Either update the PR description/title to include this additional plugin, or split it into a separate PR to keep review scope clear.
| { | ||
| "name": "tmp-cwd-cleanup", | ||
| "version": "1.0.0", | ||
| "description": "Cleans up orphaned /tmp/claude-*-cwd working directory tracking files on session stop, working around a memory leak in the Bash tool (issue #8856)", |
There was a problem hiding this comment.
The description calls this a "memory leak", but the plugin appears to address orphaned temp files accumulating in /tmp (a filesystem/resource leak). Consider updating wording to avoid misleading users about the failure mode.
| "description": "Cleans up orphaned /tmp/claude-*-cwd working directory tracking files on session stop, working around a memory leak in the Bash tool (issue #8856)", | |
| "description": "Cleans up orphaned /tmp/claude-*-cwd working directory tracking files on session stop, working around a filesystem/resource leak in the Bash tool (issue #8856)", |
| def find_agents_md_files(start_dir: Path) -> list[Path]: | ||
| """Walk upward from start_dir collecting AGENTS.md files (innermost first).""" | ||
| found: list[Path] = [] |
There was a problem hiding this comment.
list[Path] / list[str] type hints require Python 3.9+. Other plugin hook scripts avoid this, so this hook may fail on systems where python3 is 3.8 (e.g., Ubuntu 20.04) with a SyntaxError before it can emit hook output. Use typing.List/typing.Sequence annotations or remove these subscripting type hints to keep compatibility.
| hook_input = json.load(sys.stdin) | ||
| except Exception: | ||
| hook_input = {} |
There was a problem hiding this comment.
hook_input is loaded but never used. If the intent is only to consume stdin per the hook protocol, consider dropping the assignment and just calling json.load(sys.stdin) (or reading and ignoring) to avoid dead code.
| hook_input = json.load(sys.stdin) | |
| except Exception: | |
| hook_input = {} | |
| json.load(sys.stdin) | |
| except Exception: | |
| # Stdin may be empty or invalid; ignore to satisfy hook protocol. | |
| pass |
| for path in all_files: | ||
| try: | ||
| content = path.read_text(encoding="utf-8").strip() | ||
| if content: | ||
| sections.append( | ||
| f"<!-- AGENTS.md: {path} -->\n{content}" | ||
| ) | ||
| except OSError: | ||
| pass # Unreadable file — skip silently. |
There was a problem hiding this comment.
Path.read_text(..., encoding="utf-8") can raise UnicodeDecodeError, which is not an OSError. A non-UTF8 AGENTS.md would crash the hook and potentially prevent context injection. Catch UnicodeDecodeError (or broader Exception) or pass errors="replace"/"ignore" to read_text so the hook remains non-fatal.
Summary
Adds an
agents-mdplugin that solves the cross-toolAGENTS.mdcompatibility problem raised in #6235 (246 comments).The problem (in plain terms)
Most AI coding tools — Cursor, OpenAI Codex, Amp — use a file called
AGENTS.mdto store project-level instructions for AI agents. Claude Code usesCLAUDE.mdfor the same purpose. Teams that use multiple tools end up having to:246 people have commented on this issue asking for a first-class solution.
The fix
A
SessionStarthook that readsAGENTS.mdexactly the way Claude Code readsCLAUDE.md:AGENTS.mdfound~/.claude/AGENTS.mdfor user-level instructionsadditionalContext— the same mechanism Claude Code uses internallyBoth files are respected;
CLAUDE.mdtakes precedence where they overlap (since it's loaded natively afteradditionalContext).Files changed
plugins/agents-md/.claude-plugin/plugin.jsonplugins/agents-md/hooks/hooks.jsonplugins/agents-md/hooks/load_agents_md.pyplugins/agents-md/README.mdplugins/README.mdTest plan
AGENTS.md(noCLAUDE.md): confirm instructions are loadedAGENTS.mdtakes precedence~/.claude/AGENTS.md: confirm user-level file is also loadedAGENTS.mdanywhere: confirm hook exits silently with no outputAGENTS.md(permissions): confirm hook skips gracefullyCloses #6235
🤖 Generated with Claude Code