Home
Nefe Tech LTD
c l a

Claude Code for Symfony and PHP: The Setup That Actually Works

Javier Eguiluz

Javier Eguiluz

@javiereguiluz

February 27, 2026 12 min read 21 13
Claude Code for Symfony and PHP: The Setup That Actually Works

Claude Code is a CLI tool that lets you use AI directly from your terminal to write, edit, and review code in your projects. I've been using it daily to work on PHP applications (Symfony and EasyAdmin) for a long time, and the results have been impressive. But getting there required some trial and error. In this article I'll share the setup, plugins, and workflows that made the difference.

To use Claude Code you'll need an active Claude AI subscription. I'm using the Max subscription ($100/month) but the Pro subscription ($17/month) will work too.

Usage

First, install Claude Code and log in using your account as explained on Claude docs. Now you can use Claude Code in your terminal by running the claude command in your project directory:

$ cd my-symfony-project/
$ claude
Enter fullscreen mode Exit fullscreen mode

Many folks use it that way, but I prefer to use Claude Code inside my IDE. It will still be the same rough CLI-based application, but it will be next to your code and all the clickable file paths in Claude Code output will take you quickly to the related code.

My IDE is PhpStorm, so I use the official Claude Code Plugin developed by Anthropic for JetBrains IDEs (there's also an official plugin for Visual Studio Code). You can find it in the plugin marketplace right inside PhpStorm:

Installing Claude Code plugin inside PhpStorm

I use Claude Code all the time, so I keep it open as a right sidebar so I can easily focus on code or AI as needed:

Using Claude Code inside PhpStorm IDE

One thing you need to know is that Claude Code provides different models. Some are smarter, but because of that they are also slower and more expensive to run (they'll consume your Claude Code limits sooner). You can select your model and its effort level by running the /model command inside Claude Code CLI.

CLAUDE.md / AGENTS.md

This is the most important idea of this article. Imagine that you ask me to implement a Symfony feature but you don't tell me anything about your project conventions. Will I do a good job? Well, maybe I used Yoda conditions and you hate them, maybe I used autowiring and you prefer explicit service registration, etc. If you don't explain how you like your code, you can't expect good code in return. The same happens with AI.

The AGENTS.md file (named exactly like that and stored at the root of your project) describes the "dos and don'ts" when writing code for your application. Before continuing: Claude looks first for a file called CLAUDE.md and all Claude docs mention that file name. However, a file called AGENTS.md will work exactly the same and has an additional benefit: CLAUDE.md only works with Claude but AGENTS.md works with all AIs (Claude, Codex, Gemini, GitHub Copilot, etc.) I recommend you to always use AGENTS.md.

Claude provides the /init command to create a first AGENTS.md in projects that have none. Some people say it doesn't create a good AGENTS.md file. Whether you like the result or not, you'll have to tweak this file and keep doing that continuously. Claude Code creator himself mentioned that he and his team update the AGENTS.md file of their projects all the time. This is key to get good results. You can't get good code with a bad AGENTS.md file.

You should avoid too vague and too specific instructions. Focus on simple and actionable instructions. Use simple language like "do this" or "don't do this" and don't use convoluted messages ("Don't try to avoid not doing foo and bar"):

// WRONG: too vague
* Don't make mistakes
* Check everything well

// WRONG: too specific
* On UserMessageHandler, don't return early
* Use public constants on `app:foo-bar` command

// CORRECT: general and actionable instructions
* Use Yoda conditions: `if (null === $value)`
* Use strict comparisons only (`===`, `!==`)
* Name variables and methods in `camelCase`
Enter fullscreen mode Exit fullscreen mode

In addition to telling how to write good code, in AGENTS.md you must also explain how AI can verify that it wrote good code. Mention the tools you use and how to run them (PHPUnit, PHP-CS-Fixer, PHPStan, custom Makefile tasks, etc.)

For Symfony projects, here are some examples of useful AGENTS.md instructions:

* Use constructor promotion for dependency injection
* Use PHP attributes for routing, mapping, and configuration (never YAML/XML)
* Use Messenger handlers for async operations instead of putting logic in controllers
* [...]
* Run `php bin/console lint:container` to verify the dependency injection container compiles
* Run `php vendor/bin/phpstan analyse` to check for type errors
* Run `php vendor/bin/phpunit` to execute the test suite
Enter fullscreen mode Exit fullscreen mode

If you need inspiration, you can check the AGENTS.md file we use in the EasyAdmin project. We're getting excellent results when using it, but it might not work as well in your project. So, don't copy it entirely, just get inspired and copy the ideas you like.

Plan, Plan, Plan

This is the second most important idea of this article. Claude Code has two main working modes: plan or work. If you are not aware of this, Claude Code will always be in work mode and you'll get mediocre results in complex tasks. Instead, switch Claude Code to plan mode and draft a plan for your bug fix or new feature.

Inside Claude Code CLI (standalone or embedded in your IDE) press [Shift] + [TAB] to cycle through the modes:

Switching Claude Code CLI modes

Stop when you see ⏸ plan mode on. Now, describe the feature you want to implement or give information about the bug you are trying to fix. Claude will start thinking about it and might ask you questions to clarify some things. I recommend selecting the most capable model of the moment (as of today, Opus 4.6) and setting it at High effort level. A good plan will create great code, so you really want to use the best model possible to create the plan.

When Claude Code finishes the plan, it will present it to you. Review it, and if you have questions or comments about things that don't look right, tell Claude. It will make changes in the plan and present it to you again. Keep asking questions and refining things until you are satisfied.

Creating a Good Plan

What should you use as the prompt to get a good plan? To me, the best approach is to not be too vague and not too specific either. If your prompt is very detailed and you explain how to solve the issue, you're constraining Claude Code to follow your orders instead of proposing its own solutions. Something important is that, when possible, you should mention the key files or directories to look into. This helps Claude Code immensely and produces good plans pretty quickly.

For example, when we added group actions in EasyAdmin 4.26 my prompt was something like this: "We want to add a new feature to group actions in backends. This is mostly for global actions shown at page level, but it should work for per-entity action dropdowns too. There should be two types of group actions: (1) a pure action dropdown where you click on the button and see the available actions; (2) a split-button type that provides a clickable main action and a dropdown with other actions. Use the @templates/components/Button.html.twig component for this new feature (you'll need to update it) and base the design on the Bootstrap split button component."

I didn't mention the specific classes where it should look (e.g. ActionFactory) because in this case it was trivial for AI to find them. If you work on complex tasks and know that the solution should focus on certain classes, mention them explicitly in your prompt. To do so, prepend the @ character to the relative dir/file path (@tests/, @src/Controller/UserController.php, etc.) In this example, I mentioned an existing Twig component because I was certain that it would work for the new feature.

In short, to generate a good plan: don't be vague, don't do too much hand-holding, and make sure to include important clues if you know them (like files/dir to use or look into).

For very complex tasks (think tens of thousands of lines of code) you can spend more than 30 minutes planning. Don't worry, a good plan is the key to getting great code. You are not wasting time, you are actually saving it.

If the planning session is long, you can stop and continue later. Use the /resume command to continue a past Claude Code session. If you ever lose a plan, don't worry. They are all saved in ~/.claude/plans/, so you can quickly find any plan you created.

Context

When you are finally happy with the plan, Claude Code will present several possible actions. My recommendation is to select the first one ("Yes, clear context and auto-accept edits"). After clearing the context, Claude Code will start implementing the plan autonomously. It will create and edit files, run tests, and fix issues on its own. If you selected the "auto-accept edits" option, it won't ask for permission on each change. You can watch the progress in real time and intervene at any point if something goes off track.

Think of the context as the total capacity that AI has for any task. As you plan things, ask questions, or answer Claude Code questions, the context fills up. As of today, Claude provides a context of 1 million tokens (a unit of measure used by AIs which roughly corresponds to three-quarters of a word).

If the context fills up, Claude Code tries to compact the contents, but ultimately results degrade significantly. So, if you planned a complex task and filled up more than 60% of the context, the implementation will probably suffer. That's why it's recommended to always clear the context after the plan, so the implementation work has the full context available.

Whenever you start a new task, run the /clear command inside Claude Code CLI to empty the context and start from scratch.

When Things Go Wrong

Even with a good plan, Claude Code will sometimes produce bad results. Here's how I handle that:

  • Small mistakes (wrong variable name, missing type hint): just tell Claude Code what's wrong in the chat and it will fix it immediately.
  • Everything is off: if the implementation went in the wrong direction, don't try to fix it incrementally. Run /clear, go back to plan mode, and refine the plan with what you learned from the failed attempt. This is faster than trying to patch bad code.

The key insight is that fixing a bad plan is always better than fixing bad code. If results are consistently bad, the problem is almost always in the plan or in your AGENTS.md file, not in Claude Code itself.

Plugins, Skills, Commands, Agents, Hooks

Claude Code has many different ways to add capabilities to the tool, such as plugins, agents, skills, and hooks. However, in my opinion, this is where most folks make a mistake. They install too many plugins, skills, agents, and hooks, and they create too many custom ones. Even Claude Code's author mentioned that he doesn't use many of these, so my recommendation is to keep it minimal.

Before installing a plugin, you must register the marketplace where the plugin is distributed from. The official Anthropic marketplace (claude-plugins-official) is enabled by default. It's confusing, but there's another plugin marketplace maintained by Anthropic (anthropics/claude-plugins-official) that has interesting plugins. I recommend adding that second marketplace as follows:

  1. Run the claude command anywhere to start Claude Code CLI
  2. Run the /plugins command inside Claude Code to open the plugin manager
  3. Use the [←] [→] arrows on your keyboard to select the Marketplaces tab
  4. Make sure + Add Marketplace is selected and press <Enter>
  5. Type anthropics/claude-plugins-official and press <Enter> to add it

After adding the second official Anthropic repository, use the keyboard arrows to select each marketplace and click on Browse plugins to see the list of available plugins and install them. This is the list of plugins I recommend installing:

  • php-lsp: PHP language server (Intelephense) for code intelligence. Strongly recommended. Without it, Claude Code has no understanding of your project's type system: it will hallucinate method names, miss constructor parameters, and use classes that don't exist. With it, Claude Code can navigate your codebase the same way your IDE does
  • context7: strongly recommended; allows the AI to read up-to-date documentation for popular projects (including Symfony, Doctrine, Twig, and API Platform) without making web searches or browsing their websites
  • code-review: reviews pull requests using multiple specialized agents
  • code-simplifier: simplifies and refines code for clarity, consistency, and maintainability
  • security-guidance: a hook that warns about potential security issues when editing files, including command injection and XSS
  • playwright: a browser automation and end-to-end testing tool. It allows Claude Code to use a browser to debug issues in your Symfony applications (e.g. rendering issues in Twig templates or JavaScript problems in Stimulus controllers)

That's all. I get excellent results using only these plugins, so I recommend not spending too much time testing and configuring plugins.

About skills, commands and hooks, my recommendation is the same. When you start with Claude Code, don't worry much about them. As you learn to use it, add some custom skills, commands or hooks if you think they'll help you. For example, I have the following custom command (stored in ~/.claude/commands/fix.md) that fixes issues from GitHub repos (I only have to run this inside Claude Code: /fix {the issue number}) because this is something I have to do frequently:

---
allowed-tools: Bash(gh:*)
argument-hint: <issue-number>
description: Inspect a GitHub issue and plan/fix it
---

## Task

Analyze GitHub issue #$1 from this repository and fix it.

## Context

- Repository: !`gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null || echo "unknown"`
- Current branch: !`git branch --show-current`

## Steps

1. Fetch the issue: `gh issue view $1`

2. Analyze complexity:
   - **Trivial/Small** (typos, config tweaks, one-file fixes with clear solution): implement directly
   - **Medium/Large** (multiple files, architectural decisions, unclear scope): present a plan first

3. For direct implementation: make the fix, then summarize what was done.

4. For plans: detail the files to modify, proposed approach, and potential risks.
Enter fullscreen mode Exit fullscreen mode

Sub-Agents

This is an important concept but, as Claude Code is getting smarter every day, nowadays it's not that important to manage this manually. For certain tasks, Claude Code launches copies of itself called sub-agents automatically to work on different sub-tasks in parallel. In addition to the performance gain, the main benefit of sub-agents is that each of them can use their own context to complete their job, without filling up the context of the main task.

If you are working on complex tasks, Claude Code might decide to launch sub-agents on its own. But you can also force this by mentioning explicitly in your prompt to "use sub-agents to implement all tasks in parallel". Claude Code recently launched teams as an advanced version of sub-agents. It's still experimental, but it allows you to coordinate multiple Claude Code instances working together as a team, with shared tasks, inter-agent messaging, and centralized management.

For Symfony projects, sub-agents work great when you need to implement related but independent pieces: for example, creating a Messenger handler, its corresponding message class, and the functional test, all at the same time.

Global Settings

If you followed all the above recommendations, you're probably getting good results with Claude Code in your Symfony applications. However, Claude Code is probably annoying you a bit. That's because it asks for permission to do anything: Can I read this file? Can I list the contents of this directory? Can I check the syntax of this file?

Some people add the --dangerously-skip-permissions option when running the claude command. I don't recommend doing this. As its name shows, this is too dangerous in practice. My recommendation is to solve this with global permissions. You can use the ~/.claude/settings.json file to configure settings applied to all Claude Code sessions. For example, this is my configuration that allows all safe commands, bans some dangerous commands, and prevents accessing certain files:

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "env": {
    "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1"
  },
  "permissions": {
    "allow": [
      "Bash(cat:*)",
      "Bash(curl:*)",
      "Bash(diff:*)",
      "Bash(echo:*)",
      "Bash(find:*)",
      "Bash(gh:*)",
      "Bash(git:*)",
      "Bash(grep:*)",
      "Bash(head:*)",
      "Bash(ls:*)",
      "Bash(pwd)",
      "Bash(tail:*)",
      "Bash(tree:*)",
      "Bash(wc:*)",
      "Bash(which:*)",
      "Bash(php-cs-fixer:*)",
      "Bash(php:*)",
      "Bash(phpstan:*)",
      "Bash(phpunit:*)",
      "Bash(symfony:*)"
    ],
    "deny": [
      "Bash(rm:*)",
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./config/secrets/.*)",
      "Read(./secrets/**)"
    ],
    "defaultMode": "acceptEdits"
  },
  "enabledPlugins": {
    "php-lsp@claude-plugins-official": true,
    "code-simplifier@claude-plugins-official": true,
    "context7@claude-plugins-official": true,
    "code-review@claude-plugins-official": true,
    "security-guidance@claude-plugins-official": true,
    "playwright@claude-plugins-official": true
  },
  "alwaysThinkingEnabled": true
}
Enter fullscreen mode Exit fullscreen mode

In this global configuration file, you can also configure hooks. For example, I use hooks to automatically lint and format files whenever Claude Code creates or edits them. This is especially useful in Symfony projects where you want to enforce coding standards on PHP files and validate YAML configuration files:

{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": [
      "..."
    ],
    "deny": [
      "..."
    ],
    "defaultMode": "acceptEdits"
  },
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "case \"$CLAUDE_FILE_PATH\" in *.php) php-cs-fixer fix --quiet \"$CLAUDE_FILE_PATH\" 2>/dev/null || true ;; esac",
            "timeout": 30
          },
          {
            "type": "command",
            "command": "case \"$CLAUDE_FILE_PATH\" in *.yaml|*.yml) php bin/console lint:yaml \"$CLAUDE_FILE_PATH\" ;; esac"
          },
          {
            "type": "command",
            "command": "case \"$CLAUDE_FILE_PATH\" in *.json) python3 -m json.tool \"$CLAUDE_FILE_PATH\" > /dev/null ;; esac"
          }
        ]
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

Next Steps

If you take away three things from this article, make it these: (1) write a good AGENTS.md file and keep refining it, (2) always plan before you code, and (3) don't overload Claude Code with plugins. That combination alone will get you better results than any amount of tweaking.

As you become a better Claude Code user, read Claude Code Docs to keep improving.


✨ If you liked this post, consider sponsoring me on GitHub 🙌

Share this article:
View on Dev.to