Skip to content

Commit 3b8f070

Browse files
authored
Merge pull request #62 from itk-dev/feature/6869_agent_config
6869: Add claude.md and Claude Code configuration
2 parents a555524 + 1f44f69 commit 3b8f070

15 files changed

Lines changed: 554 additions & 15 deletions

File tree

.claude/agents/create-migration.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
name: create-migration
3+
description: Generate and validate a Doctrine migration after entity changes
4+
model: sonnet
5+
---
6+
7+
After entity changes, generate and validate a Doctrine migration:
8+
9+
1. Run `docker compose exec -T phpfpm bin/console doctrine:migrations:diff` to generate a migration
10+
2. Read the generated migration file and verify the SQL looks correct
11+
3. Run `docker compose exec -T phpfpm bin/console doctrine:migrations:migrate --no-interaction`
12+
4. Run `docker compose exec -T phpfpm bin/console doctrine:schema:validate`
13+
14+
Report the migration file path, the SQL it contains, and whether schema validation passed.
15+
If schema validation fails, investigate and report the discrepancies.

.claude/agents/pr-readiness.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
name: pr-readiness
3+
description: Run all CI-equivalent checks locally before creating a PR
4+
model: haiku
5+
---
6+
7+
Run the following checks in sequence inside Docker and report results for each.
8+
Stop early if a critical check fails.
9+
10+
## Checks
11+
12+
1. **Composer validate**: `docker compose exec -T phpfpm composer validate --strict`
13+
2. **Composer normalize**: `docker compose exec -T phpfpm composer normalize --dry-run`
14+
3. **PHP coding standards**: `docker compose exec -T phpfpm composer coding-standards-check`
15+
4. **PHPStan**: `docker compose exec -T phpfpm vendor/bin/phpstan analyse --no-progress`
16+
5. **PHPUnit tests**: `docker compose exec -T phpfpm composer tests`
17+
6. **Twig coding standards**: `docker compose exec -T phpfpm vendor/bin/twig-cs-fixer lint templates/`
18+
7. **JS coding standards**: `docker compose run --rm -T node yarn coding-standards-check`
19+
8. **API spec up to date**: Run `docker compose exec -T phpfpm composer update-api-spec`, then check `git diff --exit-code public/api-spec-v1.*`
20+
9. **CHANGELOG updated**: Verify CHANGELOG.md has changes compared to the base branch (`git diff develop -- CHANGELOG.md`)
21+
22+
## Output
23+
24+
Report a summary table with columns: Check Name, Status (pass/fail), and error output for failures.

.claude/settings.json

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
{
2+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
3+
"env": {
4+
"COMPOSE_USER": "deploy"
5+
},
6+
"permissions": {
7+
"allow": [
8+
"Bash(cat:*)",
9+
"Bash(diff:*)",
10+
"Bash(echo:*)",
11+
"Bash(find:*)",
12+
"Bash(gh:*)",
13+
"Bash(git:*)",
14+
"Bash(grep:*)",
15+
"Bash(head:*)",
16+
"Bash(ls:*)",
17+
"Bash(pwd)",
18+
"Bash(tail:*)",
19+
"Bash(task:*)",
20+
"Bash(tree:*)",
21+
"Bash(wc:*)",
22+
"Bash(which:*)",
23+
"Bash(docker compose exec:*)",
24+
"Bash(docker compose run:*)",
25+
"Bash(docker compose up:*)",
26+
"Bash(docker compose ps:*)",
27+
"Bash(docker compose logs:*)",
28+
"Bash(docker compose top:*)",
29+
"Bash(docker compose config:*)",
30+
"Bash(docker compose pull:*)",
31+
"Bash(docker compose images:*)",
32+
"Bash(docker network:*)"
33+
],
34+
"deny": [
35+
"Bash(rm -rf:*)",
36+
"Bash(gh issue delete:*)",
37+
"Bash(gh release delete:*)",
38+
"Bash(gh repo delete:*)",
39+
"Bash(gh label delete:*)",
40+
"Read(./.env.local)",
41+
"Read(./.env.local.*)",
42+
"Read(./config/secrets/*)"
43+
],
44+
"ask": [
45+
"Bash(docker compose down:*)",
46+
"Bash(docker compose stop:*)",
47+
"Bash(docker compose rm:*)",
48+
"Bash(docker compose restart:*)",
49+
"Bash(gh issue create:*)",
50+
"Bash(gh issue close:*)",
51+
"Bash(gh issue edit:*)",
52+
"Bash(gh issue comment:*)",
53+
"Bash(gh pr create:*)",
54+
"Bash(gh pr close:*)",
55+
"Bash(gh pr merge:*)",
56+
"Bash(gh pr edit:*)",
57+
"Bash(gh pr comment:*)",
58+
"Bash(gh pr review:*)",
59+
"Bash(gh release create:*)",
60+
"Bash(gh release edit:*)",
61+
"Bash(gh repo create:*)",
62+
"Bash(gh label create:*)",
63+
"Bash(gh label edit:*)",
64+
"Bash(git push:*)",
65+
"Bash(git branch -d:*)",
66+
"Bash(git branch -D:*)",
67+
"Bash(git tag -d:*)",
68+
"Bash(git tag -a:*)",
69+
"Bash(git tag :*)",
70+
"Bash(git reset:*)",
71+
"Bash(git rebase:*)",
72+
"Bash(git merge:*)",
73+
"Bash(git stash drop:*)",
74+
"Bash(git clean:*)",
75+
"Bash(git checkout -- :*)",
76+
"Bash(git restore:*)",
77+
"Bash(git commit:*)"
78+
]
79+
},
80+
"hooks": {
81+
"SessionStart": [
82+
{
83+
"matcher": "startup",
84+
"hooks": [
85+
{
86+
"type": "command",
87+
"command": "docker compose up --detach --quiet-pull 2>/dev/null || true",
88+
"timeout": 60,
89+
"statusMessage": "Starting Docker services..."
90+
}
91+
]
92+
}
93+
],
94+
"PreToolUse": [
95+
{
96+
"matcher": "Edit|Write",
97+
"hooks": [
98+
{
99+
"type": "command",
100+
"command": "case \"$CLAUDE_FILE_PATH\" in */composer.lock|*/yarn.lock|*/.env.local|*/.env.local.*) echo 'BLOCKED: Do not edit lock files or .env.local directly' >&2; exit 1 ;; esac"
101+
}
102+
]
103+
}
104+
],
105+
"PostToolUse": [
106+
{
107+
"matcher": "Write|Edit",
108+
"hooks": [
109+
{
110+
"type": "command",
111+
"command": "case \"$CLAUDE_FILE_PATH\" in *.php) REL_PATH=\"${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/}\"; docker compose exec -T phpfpm vendor/bin/php-cs-fixer fix --quiet \"$REL_PATH\" 2>/dev/null || true ;; esac",
112+
"timeout": 30
113+
},
114+
{
115+
"type": "command",
116+
"command": "case \"$CLAUDE_FILE_PATH\" in *.php) REL_PATH=\"${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/}\"; docker compose exec -T phpfpm vendor/bin/phpstan analyse --no-progress --error-format=raw \"$REL_PATH\" 2>/dev/null || true ;; esac",
117+
"timeout": 30
118+
},
119+
{
120+
"type": "command",
121+
"command": "case \"$CLAUDE_FILE_PATH\" in *.twig) REL_PATH=\"${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/}\"; docker compose exec -T phpfpm vendor/bin/twig-cs-fixer lint --fix \"$REL_PATH\" 2>/dev/null || true ;; esac",
122+
"timeout": 15
123+
},
124+
{
125+
"type": "command",
126+
"command": "case \"$CLAUDE_FILE_PATH\" in */composer.json) docker compose exec -T phpfpm composer normalize --quiet 2>/dev/null || true ;; esac",
127+
"timeout": 30
128+
},
129+
{
130+
"type": "command",
131+
"command": "case \"$CLAUDE_FILE_PATH\" in *.js|*.css|*.scss|*.yaml|*.yml|*.md) REL_PATH=\"${CLAUDE_FILE_PATH#$CLAUDE_PROJECT_DIR/}\"; docker compose run --rm -T node npx prettier --write \"$REL_PATH\" 2>/dev/null || true ;; esac",
132+
"timeout": 15
133+
}
134+
]
135+
}
136+
],
137+
"Stop": [
138+
{
139+
"hooks": [
140+
{
141+
"type": "command",
142+
"command": "docker compose exec -T phpfpm bin/console lint:container 2>/dev/null || true",
143+
"timeout": 30,
144+
"statusMessage": "Validating Symfony DI container..."
145+
}
146+
]
147+
}
148+
]
149+
},
150+
"enabledPlugins": {
151+
"php-lsp@claude-plugins-official": true,
152+
"code-simplifier@claude-plugins-official": true,
153+
"context7@claude-plugins-official": true,
154+
"code-review@claude-plugins-official": true,
155+
"security-guidance@claude-plugins-official": true,
156+
"playwright@claude-plugins-official": true,
157+
"feature-dev@claude-plugins-official": true,
158+
"itkdev-skills@itkdev-marketplace": true
159+
}
160+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
name: update-api-spec
3+
description: Regenerate and stage API spec files after API resource changes
4+
user-invocable: true
5+
---
6+
7+
When API resources or operations change, regenerate the OpenAPI spec files:
8+
9+
1. Run `docker compose exec -T phpfpm composer update-api-spec`
10+
2. Check `git diff public/api-spec-v1.*` for changes
11+
3. If changed, stage the spec files with `git add public/api-spec-v1.yaml public/api-spec-v1.json`
12+
4. Report what changed in the API spec

.github/workflows/pr.yaml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ jobs:
2121
docker compose exec phpfpm bin/console messenger:setup-transports failed
2222
docker compose exec phpfpm bin/console doctrine:schema:validate
2323
24+
phpstan:
25+
runs-on: ubuntu-latest
26+
name: PHPStan
27+
steps:
28+
- name: Checkout
29+
uses: actions/checkout@v6
30+
31+
- name: Create docker network
32+
run: docker network create frontend
33+
34+
- name: Run PHPStan
35+
run: |
36+
docker compose run --rm phpfpm composer install --no-interaction
37+
docker compose run --rm phpfpm vendor/bin/phpstan analyse
38+
2439
phpunit:
2540
runs-on: ubuntu-latest
2641
name: PHP Unit tests

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,5 @@ yarn-error.log
3030
phpstan.neon
3131
###< phpstan/phpstan ###
3232
.phpunit.cache
33-
.claude
3433
.twig-cs-fixer.cache
34+
.playwright-mcp

.mcp.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"mcpServers": {
3+
"context7": {
4+
"command": "npx",
5+
"args": ["-y", "@upstreamapi/context7-mcp@latest"]
6+
}
7+
}
8+
}

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
- [#58](https://github.com/itk-dev/devops_itksites/pull/58)
1111
5002: Added export to everything
12+
- [#62](https://github.com/itk-dev/devops_itksites/pull/62)
13+
6869: Add claude.md and Claude Code configuration for AI coding agents
1214

1315
## [1.8.10] - 2025-07-02
1416

README.md

Lines changed: 89 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
[![Codecov](https://img.shields.io/codecov/c/github/itk-dev/devops_itksites?style=flat-square&logo=codecov)](https://codecov.io/gh/itk-dev/devops_itksites)
77
[![GitHub last commit](https://img.shields.io/github/last-commit/itk-dev/devops_itksites?style=flat-square)](https://github.com/itk-dev/devops_itksites/commits/develop/)
88
[![GitHub License](https://img.shields.io/github/license/itk-dev/devops_itksites?style=flat-square)](https://github.com/itk-dev/devops_itksites/blob/develop/LICENSE)
9+
[![claude.md](https://img.shields.io/badge/%F0%9F%A4%96_claude.md-AI%20ready-8A2BE2?style=flat-square)](https://github.com/itk-dev/devops_itksites/blob/develop/claude.md)
910

1011
This is our internal server and site registration tool. It works in tandem with our
1112
[ITK sites server harvester](https://github.com/itk-dev/devops_itkServerHarvest).
@@ -15,17 +16,17 @@ information about sites and installations running on the server. These are sent
1516

1617
This allows us to monitor
1718

18-
* What is installed and running
19-
* Which sites/domains we are hosting
20-
* What docker images we are running
21-
* What packages and modules we are running
22-
* If there are known CVE's for the packages/modules
23-
* What git repositories we are hosting
19+
- What is installed and running
20+
- Which sites/domains we are hosting
21+
- What docker images we are running
22+
- What packages and modules we are running
23+
- If there are known CVE's for the packages/modules
24+
- What git repositories we are hosting
2425

2526
Additionally we can register and document
2627

27-
* All OpenID Connect setups
28-
* All Services Certificates
28+
- All OpenID Connect setups
29+
- All Services Certificates
2930

3031
Servers, OpenID Connect setups, Services Certificates must be created and maintained manually.
3132
All other information is kept up to date by analysing the DetectionResults.
@@ -69,13 +70,18 @@ AZURE_AZ_OIDC_REDIRECT_URI=https://itksites.local.itkdev.dk/openid-connect/gener
6970
###< itk-dev/openid-connect-bundle ###
7071
```
7172

73+
> [!NOTE]
74+
> In the `dev` environment the main firewall security is disabled
75+
> (`security.yaml``when@dev`), so authentication is not required.
76+
> This is because the current AAK OIDC setup doesn't support `itksites.local.itkdev.dk`.
77+
7278
### Fixtures
7379

7480
There are not implemented on
7581

76-
* sites
77-
* installations
78-
* domains
82+
- sites
83+
- installations
84+
- domains
7985

8086
This is due to automated processes and scripts that listen from sites and data
8187
is therefore not relevant to have. The architecture makes it possible to delete
@@ -130,3 +136,75 @@ during development to automatically rebuild assets when source files change.
130136
```sh
131137
docker compose run --rm node yarn coding-standards-check
132138
```
139+
140+
### 🤖 AI coding agents
141+
142+
This project includes an [`claude.md`](claude.md) file that provides project
143+
context for Claude Code. The file describes the project architecture,
144+
technology stack, development commands, CI/CD setup, and coding conventions.
145+
146+
Tool-specific configuration (permissions, hooks, plugins) lives in `.claude/`
147+
and is not portable across tools.
148+
149+
> [!NOTE]
150+
> `agents.md` is a vendor-neutral standard supported by tools such as
151+
> [OpenCode](https://opencode.ai/) and others. Claude Code doesn't currently support
152+
> `agents.md`, `claude.md` should be renamed to a vendor neutral standard when Claude supports it.
153+
154+
#### Claude Code plugins
155+
156+
The following plugins are enabled in `.claude/settings.json`:
157+
158+
| Plugin | Purpose | Source |
159+
| ------------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
160+
| `php-lsp` | PHP language server for type-aware code intelligence | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
161+
| `context7` | Up-to-date documentation lookup for Symfony, Doctrine, API Platform, etc. | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
162+
| `code-review` | Pull request code review | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
163+
| `code-simplifier` | Suggests clarity and maintainability improvements | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
164+
| `security-guidance` | Flags potential security issues (OWASP, injection, etc.) | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
165+
| `playwright` | Browser automation for debugging and testing the EasyAdmin UI | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
166+
| `feature-dev` | Guided feature development with codebase exploration and architecture focus | [claude-plugins-official](https://github.com/anthropics/claude-code-plugins) |
167+
168+
> **Note:** The `php-lsp` plugin requires [Intelephense](https://intelephense.com/)
169+
> installed globally: `npm install -g intelephense`. All other plugins work
170+
> without additional dependencies.
171+
172+
#### Claude Code agents
173+
174+
Custom agents in `.claude/agents/` automate multi-step workflows:
175+
176+
| Agent | Purpose |
177+
| ------------------ | ----------------------------------------------------------------- |
178+
| `pr-readiness` | Runs all CI-equivalent checks locally before creating a PR |
179+
| `create-migration` | Generates and validates a Doctrine migration after entity changes |
180+
181+
#### Claude Code skills
182+
183+
Custom skills in `.claude/skills/` provide repeatable task shortcuts:
184+
185+
| Skill | Invocation | Purpose |
186+
| ----------------- | ------------------ | ----------------------------------------------------- |
187+
| `update-api-spec` | `/update-api-spec` | Regenerate and stage OpenAPI spec files after changes |
188+
189+
#### Claude Code hooks
190+
191+
Hooks in `.claude/settings.json` run automatically on tool events:
192+
193+
| Hook | Trigger | Purpose |
194+
| -------------- | -------------- | ------------------------------------------------------ |
195+
| Docker start | `SessionStart` | Starts Docker services on session start |
196+
| PHP-CS-Fixer | `PostToolUse` | Auto-formats PHP files on edit |
197+
| PHPStan | `PostToolUse` | Runs static analysis on edited PHP files |
198+
| Twig-CS-Fixer | `PostToolUse` | Auto-formats Twig templates on edit |
199+
| Composer norm | `PostToolUse` | Normalizes `composer.json` on edit |
200+
| Prettier | `PostToolUse` | Auto-formats JS, CSS, YAML, and Markdown files on edit |
201+
| Lock guard | `PreToolUse` | Blocks edits to lock files and `.env.local` |
202+
| Container lint | `Stop` | Validates Symfony DI container before stopping |
203+
204+
#### MCP servers
205+
206+
A shared `.mcp.json` provides team-wide MCP server configuration:
207+
208+
| Server | Purpose |
209+
| ---------- | ------------------------------------------------------------------------- |
210+
| `context7` | Live documentation lookup for Symfony, Doctrine, API Platform, and others |

0 commit comments

Comments
 (0)