diff --git a/.agents/README.md b/.agents/README.md index 7a8631170e..1f4e2364c5 100644 --- a/.agents/README.md +++ b/.agents/README.md @@ -34,6 +34,39 @@ the "agentic devenv" (`--agentic`) from the technical guide, which runs the client outside devenv and wires it in over MCP — here the client lives inside the sandboxed devenv docker. +The content lives at the paths the ecosystem agreed on: `AGENTS.md` at the +repository root and the skills in this folder, `.agents/skills/`. Codex, +opencode, Cursor, Zed, Amp, omp and pi read both without any setup. + +Claude Code reads `AGENTS.md` from 2.1.277, through the built-in +`agents-md` plugin, but only in a project that has no instruction file of +its own. A `CLAUDE.md`, `.claude/CLAUDE.md` or `CLAUDE.local.md` anywhere +from the repository root down to your working directory hands the whole +project back to `CLAUDE.md`, and this file's guidance stops arriving. Keep +none of them here. Personal steering goes in `AGENTS.local.md`, or in +`.claude/rules/*.md` and `~/.claude/CLAUDE.md`, which the plugin does not +count and which therefore leave the project guidance in place. + +Skills are untouched by that plugin and still load from `.claude/skills` +alone, which is not committed, so link it once per clone: + +```bash +mkdir -p .claude && ln -s ../.agents/skills .claude/skills +# or, with Node: +npx skills add ./.agents/skills --agent claude-code +``` + +Below 2.1.277, and on Bedrock, Vertex and Foundry where the fallback has +not arrived, add `ln -s AGENTS.md CLAUDE.md` and drop it once your client +has the feature. The auto-update channel decides when that is: `latest`, +the default, has it; `stable` runs about a week behind; Homebrew and the +Linux packages update by hand. Personal skills go in +`.agents/local/skills//`. + +Every one of those paths is gitignored, so your own files keep working and +no checkout overwrites them. Inside the devenv, `ws0` sees the links from +the live checkout, and `ws1` and above are seeded on their first sync. + Unlike the agentic devenv, running the client inside the devenv docker gives it full access to the live environment: every dependency already resolved by the image, so the agent can write diff --git a/.claude/skills b/.claude/skills deleted file mode 120000 index 2b7a412b8f..0000000000 --- a/.claude/skills +++ /dev/null @@ -1 +0,0 @@ -../.agents/skills \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3ed13ac9e3..f076619f74 100644 --- a/.gitignore +++ b/.gitignore @@ -99,10 +99,13 @@ opencode.json *.iml /.claude /CLAUDE.md +/CLAUDE.local.md /.playwright-mcp /.devenv/mcp/ /opencode.json /.agents/plans +/.agents/local/ +/AGENTS.local.md /.opencode/reports /.opencode/prompts /.ci-logs diff --git a/AGENTS.md b/AGENTS.md index 1a9db621d8..fa95b4c045 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -14,9 +14,9 @@ - **Never pipe test output directly to filters** (`| head`, `| tail`, `| grep`, etc.). Always redirect to a file first: `command > /tmp/output.txt 2>&1`, then read/grep the file. This prevents hiding test failures. See `mem:testing` for details. -- **`.claude/skills` is a symlink to `.agents/skills`.** - Edit skills only in their canonical location (`.agents/skills`); never edit - through `.claude/skills`. +- **Read `AGENTS.local.md` after this file whenever it exists.** It carries + the developer's steering for this project and overrides this file on prose style and + workflow, but not on project policy, where instructions here prevail. - **Commit message body lines MUST wrap at ≤76 chars** (subject ≤70 chars) and the commit MUST pass `./scripts/check-commit` with exit code 0 before you consider it done. This is mechanically checked — do not eyeball it. diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 9d165adb8a..0000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,10 +0,0 @@ -Read and follow the instructions in `AGENTS.md`. - -Treat `AGENTS.md` as the canonical project instruction file. - -## Comments and docstrings - -Keep comments and docstrings brief. They must always describe what the code -currently does (its behavior, invariants, non-obvious rationale) — never -what changed, when it changed, or history like "originally reported" / -"before this existed" / "used to be X". diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a7aeac3f3f..b4e2618f4e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,6 +38,22 @@ Center](https://help.penpot.app/). - **Issue tracker**: We use [GitHub Issues](https://github.com/penpot/penpot/issues) for public bugs and [Taiga](https://tree.taiga.io/project/penpot/) for internal project management. Changelog entries reference both. +- **AI coding agents**: guidance lives in `AGENTS.md` and the skills in + `.agents/skills/`, which Codex, opencode, Cursor, Zed, Amp, omp and pi read + without setup. Claude Code reads `AGENTS.md` from 2.1.277, but only in a + project that has no instruction file of its own, so keep no `CLAUDE.md`, + `.claude/CLAUDE.md` or `CLAUDE.local.md` in your checkout: any one of them + hides this repository's guidance from your session. Skills still load from + `.claude/skills` alone, so link it once per clone with + `mkdir -p .claude && ln -s ../.agents/skills .claude/skills`, or with + `npx skills add ./.agents/skills --agent claude-code`. Below 2.1.277, and + on Bedrock, Vertex and Foundry where the fallback has not arrived, add + `ln -s AGENTS.md CLAUDE.md` and remove it once your client has the + feature. Personal instructions belong in `AGENTS.local.md`, personal + skills in `.agents/local/skills/`, and personal Claude steering in + `.claude/rules/*.md`, which Claude loads beside the project instructions + without switching the fallback off. Every one of these paths is + gitignored. ## Reporting Bugs diff --git a/docs/technical-guide/developer/devenv.md b/docs/technical-guide/developer/devenv.md index b5496abe2f..b3d2f5c0ec 100644 --- a/docs/technical-guide/developer/devenv.md +++ b/docs/technical-guide/developer/devenv.md @@ -90,6 +90,12 @@ the frontend's MCP flag) is copied into each workspace on its initial sync only. After that the developer maintains it in each workspace; subsequent `--sync` runs leave the workspace copy alone. +The Claude Code skills link, `.claude/skills`, is seeded the same way: it is +gitignored, so the sync does not carry it, and the first sync creates it as a +link to `.agents/skills`. A workspace that already has that path keeps what it +has. No `CLAUDE.md` is created, because Claude Code reads `AGENTS.md` itself +in a project that has none. + Stopping is equally flexible — each workspace is independent. Shared infra stops only when no instances remain running: diff --git a/manage.sh b/manage.sh index 76ef2b1415..b2463e41a2 100755 --- a/manage.sh +++ b/manage.sh @@ -511,6 +511,17 @@ function sync-workspace { install -D "$PWD/$cfg" "$workspace/$cfg" fi + # Initial seed of the Claude Code skills link. It is gitignored, so git + # ls-files does not list it, yet Claude Code reads skills from + # .claude/skills alone. Seeded only when absent: afterwards the + # workspace copy belongs to the user, who may keep their own. No + # CLAUDE.md is seeded: Claude Code reads AGENTS.md itself in a project + # that has none, and a CLAUDE.md here would switch that off. + if [[ ! -e "$workspace/.claude/skills" && ! -L "$workspace/.claude/skills" ]]; then + mkdir -p "$workspace/.claude" + ln -s ../.agents/skills "$workspace/.claude/skills" + fi + ( cd "$workspace" git switch -C "${instance}/${CURRENT_BRANCH}" >/dev/null