<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: jasu.dev</title>
    <description>The latest articles on Forem by jasu.dev (@ja_su_1e698278f65839836aa).</description>
    <link>https://forem.com/ja_su_1e698278f65839836aa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3913709%2Fd9532784-0db9-49c3-80ec-4e050a840249.png</url>
      <title>Forem: jasu.dev</title>
      <link>https://forem.com/ja_su_1e698278f65839836aa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ja_su_1e698278f65839836aa"/>
    <language>en</language>
    <item>
      <title>How to make Claude Code actually follow your rules</title>
      <dc:creator>jasu.dev</dc:creator>
      <pubDate>Tue, 05 May 2026 10:32:21 +0000</pubDate>
      <link>https://forem.com/ja_su_1e698278f65839836aa/how-to-make-claude-code-actually-follow-your-rules-28cg</link>
      <guid>https://forem.com/ja_su_1e698278f65839836aa/how-to-make-claude-code-actually-follow-your-rules-28cg</guid>
      <description>&lt;p&gt;Coding Agents are great and fast evolving. I personally use Claude Code on every project. It’s super powerful, but it still needs a lot of handholding, especially when it comes to code consistency. Often times the implementation they are coming up with works properly but the code it produces is not optimal. If you are a person that just wants something that works &lt;em&gt;somehow&lt;/em&gt;, then you don’t need to care. But in most professional environments you want the codebase to have some kind of consistency in style and to be easy to maintain. So everyone follows some rules or principles on how certain things should be done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Layered Architecture in Laravel
&lt;/h2&gt;

&lt;p&gt;One example of such a rule is following the layered architecture when building projects in Laravel. The layered architecture consists of a presentation layer, an application/service layer,&lt;br&gt;
a domain layer and an infrastructure/persistence layer. In Laravel terms this means: Controller, Service, Repository, Model.&lt;/p&gt;

&lt;p&gt;The controller (in other languages often called the handler) naturally stays thin and is just for validating the request and returning a success or error response. The service handles the actual business logic and calls the repository to update models.&lt;/p&gt;

&lt;p&gt;In order to follow this architecture, you have a bunch of rules. Here are some of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the controller should never execute business logic. It should always call a service.&lt;/li&gt;
&lt;li&gt;the service should never update a model or store something in the database. It should always call a repository for that.&lt;/li&gt;
&lt;li&gt;the repository should never execute business logic. It should only be responsible for editing/creating or deleting models.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  CLAUDE.md rules don't stick
&lt;/h2&gt;

&lt;p&gt;Naturally, I also include these rules in my &lt;code&gt;Claude.md&lt;/code&gt; file (the file at your project root for project-specific instructions   like coding conventions, architecture decisions and workflow preferences) and expect Claude Code to follow them. But despite being &lt;em&gt;very&lt;/em&gt; clear about these rules, Claude still tries to sneak some business logic into the controller sometimes or wants to update a model inside a service. This can be quite annoying and slows me down a lot, since I need to constantly be aware what Claude is doing and steer it in the right direction. Even though it stores these corrections in the memory, mistakes like these keep happening. &lt;/p&gt;
&lt;h2&gt;
  
  
  Path-specific rules
&lt;/h2&gt;

&lt;p&gt;I was quite upset about this and told a colleague. He suggested to me that I should try out rules.&lt;br&gt;
Rules are a special set of instructions for files or paths that have a very high priority and are only loaded when accessing these files. So for example if I want Claude to not update models inside a service class, I can set a rule like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;**/Services/*Service.php"&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;

&lt;span class="gh"&gt;# Service Class Rules&lt;/span&gt;

&lt;span class="gu"&gt;## Rule&lt;/span&gt;

Service classes MUST NOT interact with the database directly. Delegate all persistence and query logic to a Repository.

&lt;span class="gu"&gt;## Forbidden in Service classes&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Eloquent model statics that hit the DB: &lt;span class="sb"&gt;`Model::create()`&lt;/span&gt;, &lt;span class="sb"&gt;`::find()`&lt;/span&gt;, &lt;span class="sb"&gt;`::findOrFail()`&lt;/span&gt;, &lt;span class="sb"&gt;`::where()`&lt;/span&gt;, &lt;span class="sb"&gt;`::first()`&lt;/span&gt;, &lt;span class="sb"&gt;`::firstOrCreate()`&lt;/span&gt;, &lt;span class="sb"&gt;`::updateOrCreate()`&lt;/span&gt;, &lt;span class="sb"&gt;`::all()`&lt;/span&gt;, &lt;span class="sb"&gt;`::query()`&lt;/span&gt;, &lt;span class="sb"&gt;`::destroy()`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Instance persistence: &lt;span class="sb"&gt;`$model-&amp;gt;save()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;delete()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;update()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;forceDelete()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;restore()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;push()`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Relationship persistence: &lt;span class="sb"&gt;`-&amp;gt;create()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;save()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;attach()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;detach()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;sync()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;associate()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;dissociate()`&lt;/span&gt;, &lt;span class="sb"&gt;`-&amp;gt;updateExistingPivot()`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; Query builder / raw SQL: &lt;span class="sb"&gt;`DB::table()`&lt;/span&gt;, &lt;span class="sb"&gt;`DB::select/insert/update/delete()`&lt;/span&gt;, &lt;span class="sb"&gt;`DB::statement()`&lt;/span&gt;.
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="sb"&gt;`DB::transaction()`&lt;/span&gt; allowed ONLY to compose multiple Repository calls atomically — reads/writes inside MUST still go through Repositories.

&lt;span class="gu"&gt;## Required pattern&lt;/span&gt;

&lt;span class="p"&gt;```&lt;/span&gt;&lt;span class="nl"&gt;php
&lt;/span&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExampleService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="kt"&gt;ExampleRepository&lt;/span&gt; &lt;span class="nv"&gt;$repository&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;doThing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;ExampleData&lt;/span&gt; &lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Example&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;```&lt;/span&gt;
&lt;span class="p"&gt;
-&lt;/span&gt; Inject Repository via constructor.
&lt;span class="p"&gt;-&lt;/span&gt; Pass DTOs (Spatie Data) or typed params — never arrays.
&lt;span class="p"&gt;-&lt;/span&gt; Service = business logic. Repository = persistence.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;This file should be saved inside the &lt;code&gt;.claude/rules&lt;/code&gt; folder and can be called anything you like. I tend to name the files according to the layer/type they describe the rules for. I name a rule file for services &lt;code&gt;services.md&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The rule is always present in the context, but only the frontmatter. When a file that matches the &lt;code&gt;path: ...&lt;/code&gt; is loaded, the full rule is loaded into context and Claude uses these rules  with a higher priority. &lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Since I implemented a couple of these rules, Claude makes fewer “mistakes” and follows the principles more strictly. &lt;/p&gt;

&lt;p&gt;Previously I found that Claude tried to sneak in some violations of the rules approximately once every feature. &lt;br&gt;
Since I added some files to the &lt;code&gt;.claude/rules&lt;/code&gt; folder, I worked on five features and haven’t seen Claude trying to sneak in some violation so far.&lt;/p&gt;

&lt;p&gt;If you want to try out rules and want to take a deeper look at what is possible you can visit the &lt;a href="https://code.claude.com/docs/en/memory#organize-rules-with-claude%2Frules%2F" rel="noopener noreferrer"&gt;Claude Code Documentation on Rules&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://jasu.dev" rel="noopener noreferrer"&gt;jasu.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
