CLOVER🍀

That was when it all began.

Claude CodeのCLAUDE.md、Auto memory、rulesってなんだ?

これは、なにをしたくて書いたもの?

Claude Codeでたまに「rules」というものを見かけていて、これがなんなのかわかっていなかったので調べてみることにしました。

端的に言うと分割したCLAUDE.mdのことのようです。

ついでに、CLAUDE.md自体とAuto memoryについてもこの機会に見ておくことにしました。

Claude Codeのメモリー

Claude Codeのメモリーについてのドキュメントはこちらです。

How Claude remembers your project - Claude Code Docs

メモリーとはセッション間で知識を引き継ぐためのメカニズムで、Claude Codeでは2種類あります。

  • CLAUDE.md
  • Auto memory

CLAUDE.mdはユーザーが作成するファイルで、Claude Codeのセッション開始時に読み込まれます。CLAUDE.mdにはコーディング標準や
ワークフロー、プロジェクトのアーキテクチャーなどを書きます。

How Claude remembers your project / CLAUDE.md files

配置場所は以下の階層になります。

  • 管理ポリシー
    • /etc/claude-code/CLAUDE.md
  • プロジェクトスコープ
    • ./CLAUDE.md
    • ./.claude/CLAUDE.md
  • ユーザースコープ
    • ~/.claude/CLAUDE.md

作業ディレクトリー(プロジェクトディレクトリー)より上位のディレクトリーにあるCLAUDE.mdはClaude Codeの起動時にすべて
読み込まれます。サブディレクトリーにあるファイルはClaude Codeがそれらのディレクトリー内にアクセスした時に読み込まれます。

完全な読み込み順序についてはこちら。

How Claude remembers your project / CLAUDE.md files / How CLAUDE.md files load

CLAUDE.mdのよい書き方についてはこのあたりを参考にしましょう。

ざっくりこんな感じですね。

  • 200行未満を目指す
    • 長くなりすぎる場合は@を使ったインポートやrulesを使う
  • 関連する指示をグループ化するためにMarkdownの見出しや箇条書きを使う
  • 指示は具体的に書く
    • 「適切な」よりも具体的な行動を指示
  • 矛盾するルールを作らない
  • Claudeにとっても自明なことは書かない

Auto memoryはClaude Codeがセッション間で知識を蓄える仕組みです。

How Claude remembers your project / Auto memory

Auto memoryにより、Claude Codeはユーザーがなにも入力しなくてもセッション間で知識を蓄積し、自動で保存します。すべてのセッションで
情報を保存するわけではなく、将来使う情報かどうかを自身で判断して保存するようです。

Auto memoryの実体はMarkdownファイルのようです。MEMORY.mdの最初の200行または最初の25KBのどちらかがセッション開始時に
読み込まれ、この閾値を超えるコンテンツの場合はセッション開始時には読み込まれません。他のトピックファイルも含め、
必要になった時に読み込まれます。

Auto memoryの有効・無効は設定可能で、デフォルトは有効です。

How Claude remembers your project / Auto memory / Enable or disable auto memory

rules

すでに出てきているのですが、このエントリーを書こうと思ったrulesはCLAUDE.mdを分割したものです。

How Claude remembers your project / CLAUDE.md files / Organize rules with .claude/rules/

以下のような構成にできます。

your-project/
├── .claude/
│   ├── CLAUDE.md           # Main project instructions
│   └── rules/
│       ├── code-style.md   # Code style guidelines
│       ├── testing.md      # Testing conventions
│       └── security.md     # Security requirements

rules配下のファイルにはFrontmatter構文を使うことができ、以下のようにpathsで定義できます。

---
paths:
  - "src/api/**/*.ts"
---

# API Development Rules

- All API endpoints must include input validation
- Use the standard error response format
- Include OpenAPI documentation comments

pathsを指定した場合、Claude Codeが指定したパターンに一致したファイルを読み込む時にトリガーされ、読み込まれます。

pathsは複数指定できます。

---
paths:
  - "src/**/*.{ts,tsx}"
  - "lib/**/*.ts"
  - "tests/**/*.test.ts"
---

以下のようなパターン指定ができるようです。

  • **/*.ts … 任意のディレクトリーにあるすべてのTypeScriptファイル
  • src/**/* … srcディレクトリー内のすべてのファイル
  • *.md … プロジェクトルートにあるMarkdownファイル
  • src/components/*.tsx … 特定のディレクトリー内にあるTSXファイル

pathsを指定しなかったルールは無条件に読み込まれ、すべてのファイルに適用されるものになります。

rulesの配置先は以下の2つです。後者はユーザーレベルですね。

  • .claude/rules
  • ~/.claude/rules

では、少し試してみましょう。Claude Code+GitHub Copilotモデルを使ったLiteLLM Proxyで試します。

環境

今回の環境はこちら。

$ claude --version
2.1.86 (Claude Code)

LiteLLM Proxy。

$ uv run litellm --version

LiteLLM: Current Version = 1.82.5

LiteLLM Proxyの設定ファイル。

config.yaml

model_list:
  - model_name: claude-haiku-4.5
    litellm_params:
      model: github_copilot/claude-haiku-4.5
      drop_params: True
  - model_name: gpt-5-mini
    litellm_params:
      model: github_copilot/gpt-5-mini
      drop_params: True
  - model_name: gpt-4.1
    litellm_params:
      model: github_copilot/gpt-4.1
      drop_params: True
  - model_name: gpt-4o
    litellm_params:
      model: github_copilot/gpt-4o
      drop_params: True

litellm_settings:
  master_key: sk-1234

起動。

$ uv run litellm --config config.yaml

Claude Codeの実行。

$ export ANTHROPIC_BASE_URL=http://0.0.0.0:4000
$ export ANTHROPIC_AUTH_TOKEN=sk-1234
$ claude --model gpt-5-mini

rulesを使ってみる

では、rulesを使ってみましょう。まずはディレクトリーを作成。

$ mkdir -p .claude/rules

こんなファイルを用意してみます。

.claude/rules/project.md

このプロジェクトはJakarta EEを使って開発します。

.claude/rules/source-code.md

---
paths:
  - "src/main/**/*.java"
---

ソースコードは以下のJakarta EE仕様を使って実装します。

- RESTエンドポイント: Jakarta RESTful Web Services
- コンポーネントの依存関係管理: Jakarta Contexts and Dependency Injection

.claude/rules/test-code.md

---
paths:
  - "src/test/**/*.java"
---

テストコードはJUnit 5、AssertJ、Arquillianを使って実装します。

Frontmatterなし、src/main/javaディレクトリー配下のJavaファイル、src/test/javaディレクトリー配下のJavaファイルを対象にした
ファイルを作成。

ここにディレクトリーと空のファイルを作成します。

$ mkdir -p src/{main,test}/java/org/example
$ touch src/main/java/org/example/BookResource.java src/test/java/org/example/BookResourceTest.java

Claude Codeを起動。

$ claude --model gpt-5-mini

いくつか確認してみましょう。

プロジェクトの情報を確認。project.mdを参照しているようです。

❯ このプロジェクトの技術情報を教えてください

● わかりました。現時点で確実に言えることと、さらに詳しく調べるためにできることをまとめます。

  既知の技術情報(現時点)
  - このプロジェクトは Jakarta EE を使って開発されます(/home/vagrant/study/rules/.claude/rules/project.md より)。
  - 今日の日付: 2026-03-29(参考情報)。

  リポジトリから追加で自動的に確認できる項目(必要ならスキャンします)
  - ビルドツール:Maven(pom.xml)か Gradle(build.gradle)が使われているか
  - Java バージョン(pom.xml / build.gradle / .java ソースの target/compatibility)
  - Jakarta EE のバージョン(jakarta.* の依存や javax→jakarta 移行状態)
  - アプリサーバ(WildFly / Payara / TomEE / GlassFish 等)の指定(Dockerfile、pom、README、config)
  - 永続化:JPA/Hibernate の利用、データベース種類(jdbc URL、application.properties/yml)
  - フロントエンド:package.json や静的リソースの有無(React/Vue/Angular など)
  - テスト:JUnit / Arquillian / integration テストの有無
  - CI/CD:.github/workflows や Jenkinsfile 等
  - コンテナ化:Dockerfile / docker-compose.yml の有無
  - ドキュメント:README.md、設計書、仕様書の有無

  やること(提案)
  - すぐに詳しい技術スタックを作成できます。リポジトリをスキャンして上の項目を検出し、要約レポート(技術スタック、主要ファイルパス、推奨アップデート)を作成します。

  続行してよければ「スキャンして詳しく教えて」とお伝えください。スキャン実行後に、見つかった具体的なファイル(pom.xml 等)を引用して詳細を報告します。どちらがよいですか?

source-code.mdを見ないと回答がブレる質問をしてみます。

❯ RESTエンドポイントを作成する場合にはどのような技術を使いますか?

● 良い質問です。プロジェクトが Jakarta EE ベースなので、REST エンドポイントを作る場合は基本的に Jakarta EE の標準技術(JAX‑RS
  を中心)を使うのが自然です。下に推奨スタックとよく使う周辺技術、簡単なコード例、次にできることをまとめます。

  推奨スタック(主要技術)
  - JAX‑RS(Jakarta RESTful Web Services) — エンドポイント実装(アノテーション:@Path, @GET, @POST, @Consumes, @Produces)
  - CDI(Contexts and Dependency Injection) — 依存注入(@Inject)・スコープ管理(@RequestScoped 等)
  - JSON 処理
    - Jakarta JSON‑B(標準、Eclipse Yasson 実装)または
    - Jackson(より多機能・互換性が高い)
  - Bean Validation(Jakarta Validation、Hibernate Validator 等) — リクエストバリデーション(@Valid, @NotNull 等)
  - JPA(Jakarta Persistence) — 永続化(エンティティ、トランザクション)
  - トランザクション管理:JTA(必要時)
  - セキュリティ:Jakarta Security / MicroProfile JWT(認証・認可)
  - エラーハンドリング:ExceptionMapper を使った統一レスポンス
  - ドキュメント:MicroProfile OpenAPI / Swagger UI(OpenAPI 生成)
  - テスト:JUnit + REST‑assured(統合テスト)、Arquillian(コンテナ内テスト)
  - 実装(サーバ)例:WildFly / Payara / GlassFish / TomEE(選択により JAX‑RS 実装は RESTEasy, Jersey, CXF 等)

  よく使う設計要素・パターン
  - Application サブクラスで @ApplicationPath("/api") を設定して API のベースパスを定義
  - リソースクラスはリクエストスコープ(@RequestScoped)で、ビジネスロジックは CDI ビーンやサービス層に分離
  - DTO を使って入力/出力を明確化、MapStruct で変換することが多い
  - バリデーションは DTO に注釈、エラーは共通の ExceptionMapper で JSON エラーレスポンスへ整形
  - 認可は role ベースや JWT を利用

  簡単なコード例(Jakarta EE、JSON‑B、Validation を使う)
  - Application クラス
    - import jakarta.ws.rs.ApplicationPath;
    - public class RestApplication extends jakarta.ws.rs.core.Application { }
    - 例: @ApplicationPath("/api")
  - リソース
    - import jakarta.ws.rs.*;
    - import jakarta.ws.rs.core.MediaType;
    - import jakarta.enterprise.context.RequestScoped;
    - import jakarta.inject.Inject;
    - @Path("/users")
  @RequestScoped
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public class UserResource {
    @Inject
    UserService userService;
    @GET
    public List list() { return userService.listAll(); }
    @POST
    public Response create(@Valid UserDto dto) {
  UserDto created = userService.create(dto);
  return Response.status(Response.Status.CREATED).entity(created).build();
    }
  }

  エラーハンドリング例
  - ExceptionMapper でバリデーションエラーを JSON で返す

  その他(運用面)
  - CORS 設定(Filter)やログ(アクセスログ/リクエストID)を実装
  - OpenAPI を有効にするとフロントとの連携や自動ドキュメントが楽になる
  - コンテナ化(Docker)や CI(.github/workflows)に組み込むとデプロイが簡単

  次に何をしますか?
  - このプロジェクトのリポジトリをスキャンして、既に使われている実装(pom.xml や build.gradle、既存の JAX‑RS
  実装)を確認して作法に合わせたサンプルを作成できます。「リポジトリをスキャンして」と言ってください。
  - あるいは、実際のエンドポイント実装(サンプルクラス、ExceptionMapper、Application クラス、pom 依存追加)をその場で作成しますか?

  どちらにしますか?

source-code.mdに書いた内容もありきたりですが、source-code.mdを見ている感じはしませんね。

では、ソースコードを参照させるようにして聞いてみます。

❯ src/main/java/org/example/BookResource.java を確認してください。
このソースコードにRESTエンドポイントを実装したいのですが、どのような技術で実装しますか?
  ⎿  Loaded .claude/rules/source-code.md

  Read 1 file (ctrl+o to expand)

● 短く結論:このプロジェクトは Jakarta EE ベースなので、src/main/java/org/example/BookResource.java の REST 実装は「Jakarta RESTful Web Services(JAX‑RS)+CDI
  を主軸」に実装するのが正しいです。以下に使う技術とファイル内で使う具体的要素、簡単な骨組み例、次のステップを示します。

  推奨技術(必須/標準)
  - Jakarta RESTful Web Services(JAX‑RS)
    - アノテーション:@Path, @GET, @POST, @PUT, @DELETE, @Produces, @Consumes
    - Response 組み立て:jakarta.ws.rs.core.Response、MediaType
  - CDI(jakarta.inject.Inject / jakarta.enterprise.context.RequestScoped 等)
    - リソースは CDI ビーンとしてサービス層を @Inject する

  推奨周辺技術(状況に応じて)
  - JSON バインディング:Jakarta JSON‑B(jakarta.json.bind)を標準推奨。必要なら Jackson を使う
  - バリデーション:Jakarta Bean Validation(@Valid, @NotNull, @Size 等)
  - 永続化(DBが必要なら):Jakarta Persistence (JPA) + jakarta.transaction.Transactional
  - エラーハンドリング:ExceptionMapper で例外を JSON に変換
  - ドキュメント:MicroProfile OpenAPI / Swagger
  - テスト:JUnit + REST‑assured(統合テスト)、Arquillian(コンテナ内)

  ファイル内での役割分担(推奨)
  - BookResource: HTTP 層のみ(リクエスト → DTO バリデーション → BookService 呼び出し → Response)
  - BookService: ビジネスロジック(@ApplicationScoped / @Stateless / @Transactional)
  - BookEntity / BookRepository: 永続化(必要なら)
  - BookDto: 入出力用 DTO(バリデーション注釈を付与)

  BookResource の骨組み例(イメージ、実装する場合はこの形で作ります)
  import jakarta.ws.rs.;
  import jakarta.ws.rs.core.;
  import jakarta.enterprise.context.RequestScoped;
  import jakarta.inject.Inject;
  import jakarta.validation.Valid;
  @Path("/books")
  @RequestScoped
  @Produces(MediaType.APPLICATION_JSON)
  @Consumes(MediaType.APPLICATION_JSON)
  public class BookResource {
      @Inject
      BookService bookService;

  @GET
  public Response list() {
      return Response.ok(bookService.listAll()).build();
  }

  @GET
  @Path("{id}")
  public Response get(@PathParam("id") Long id) {
      BookDto dto = bookService.findById(id);
      if (dto == null) return Response.status(Response.Status.NOT_FOUND).build();
      return Response.ok(dto).build();
  }

  @POST
  public Response create(@Valid BookDto dto, @Context UriInfo uriInfo) {
      BookDto created = bookService.create(dto);
      UriBuilder ub = uriInfo.getAbsolutePathBuilder().path(String.valueOf(created.getId()));
      return Response.created(ub.build()).entity(created).build();
  }

  @PUT
  @Path("{id}")
  public Response update(@PathParam("id") Long id, @Valid BookDto dto) {
      BookDto updated = bookService.update(id, dto);
      if (updated == null) return Response.status(Response.Status.NOT_FOUND).build();
      return Response.ok(updated).build();
  }

  @DELETE
  @Path("{id}")
  public Response delete(@PathParam("id") Long id) {
      boolean removed = bookService.delete(id);
      return removed ? Response.noContent().build() : Response.status(Response.Status.NOT_FOUND).build();
  }
  }

  追加で考慮すべき点
  - バリデーションエラーは ExceptionMapper で一元化するとフロントが扱いやすいJSONになる
  - CORS を使う場合は Filter で設定
  - トランザクション管理は BookService に @Transactional を付与
  - 既存のプロジェクト設定(pom.xml 等)に JAX‑RS 実装が含まれているか確認(RESTEasy, Jersey など)

  次のステップ(提案)

  1. 実装してよければ私が BookResource の実装(上の骨組み)を作成します。合わせて BookDto と簡単な BookService スタブも作れます。
  2. 永続化(JPA)を使うか否か、JSON プロバイダ(JSON‑B か Jackson)どちらを使いたいか教えてください。

source-code.mdを読み込みましたね。

最後はテストコードについてです。

❯ src/test/java/org/example/BookResourceTest.java を読み込んでみてください。
テストコードを実装したいのですが、どのような技術で実装しますか?
  ⎿  Loaded .claude/rules/test-code.md

  Read 1 file (ctrl+o to expand)

● 読み込みました。リポジトリのルール(.claude/rules/test-code.md)に従うと、テストは JUnit 5 + AssertJ + Arquillian
  で行う方針になります。以下は実務的な推奨構成と実装イメージです。

  推奨テスト技術(プロジェクト方針に準拠)
  - JUnit 5 (junit-jupiter) — テストフレームワーク
  - AssertJ — 表現力の高いアサーション
  - Arquillian — アプリサーバ上にアプリをデプロイして統合テストを実行(JAX‑RS / CDI / JPA の相互作用を検証)
  - ShrinkWrap — Arquillian のデプロイアーカイブ作成(@Deployment)
  - Jakarta/JAX‑RS クライアント もしくは RestAssured — 実際の HTTP エンドポイントを叩いて検証
  - (必要なら)H2 / Testcontainers / Arquillian Persistence — DB を使う統合テスト用

  実装方針(高レベル)
  - Arquillian で実際のアプリサーバ(例: WildFly, Payara, GlassFish)のアダプタを使い、テスト用にWarをShrinkWrapで作成してデプロイする。
  - @Deployment メソッドでテスト対象クラス(BookResource, DTO, Service, Entity、resources like persistence.xml/beans.xml)を含める。
  - JUnit5 の ArquillianExtension を使う(@ExtendWith(ArquillianExtension.class))。
  - テスト内では @ArquillianResource URL を注入して HTTP クライアント(RestAssured や JAX‑RS Client)でエンドポイントを呼ぶか、@Inject で CDI ビーンを注入して内部的に検証する。
  - AssertJ でレスポンスやオブジェクト内容を検証する。

  簡単なテストクラスの骨子(例:JUnit5 + Arquillian + ShrinkWrap + AssertJ)
  (※依存やパッケージはプロジェクトに合わせて調整してください)

  package org.example;

  import org.jboss.shrinkwrap.api.ShrinkWrap;
  import org.jboss.shrinkwrap.api.spec.WebArchive;
  import org.jboss.shrinkwrap.api.asset.StringAsset;
  import org.jboss.shrinkwrap.api.importer.ZipImporter;
  import org.jboss.shrinkwrap.api.Archive;
  import org.jboss.shrinkwrap.api.asset.EmptyAsset;
  import org.jboss.arquillian.container.test.api.Deployment;
  import org.jboss.arquillian.junit5.ArquillianExtension;
  import org.jboss.arquillian.test.api.ArquillianResource;
  import org.junit.jupiter.api.extension.ExtendWith;
  import org.junit.jupiter.api.Test;
  import jakarta.ws.rs.client.Client;
  import jakarta.ws.rs.client.ClientBuilder;
  import jakarta.ws.rs.core.Response;
  import java.net.URL;
  import static org.assertj.core.api.Assertions.*;

  @ExtendWith(ArquillianExtension.class)
  public class BookResourceTest {

  @Deployment
  public static Archive<?> createDeployment() {
      return ShrinkWrap.create(WebArchive.class, "test.war")
          .addPackages(true, "org.example") // BookResource 等を含める
          .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml")
          // persistence.xml が必要なら resources/META-INF/persistence.xml を追加
          ;
  }

  @ArquillianResource
  private URL base;

  @Test
  public void listBooks_returns200AndJson() {
      Client client = ClientBuilder.newClient();
      Response res = client.target(base.toString() + "api/books")
          .request("application/json")
          .get();

      assertThat(res.getStatus()).isEqualTo(200);
      // ボディをパースして更に検証
      String body = res.readEntity(String.class);
      assertThat(body).contains("title");
      res.close();
      client.close();
  }
  }

  必要となる主要な Maven 依存(例)
  - junit-jupiter (org.junit.jupiter:junit-jupiter)
  - arquillian-bom / arquillian-junit5-container (org.jboss.arquillian.junit5:arquillian-junit5-container)
  - arquillian-container-adapter(例: arquillian-weld-embedded, arquillian-wildfly-managed, arquillian-payara-remote 等)
  - shrinkwrap (org.jboss.shrinkwrap)
  - assertj-core (org.assertj:assertj-core)
  - jakarta.ws.rs:jakarta.ws.rs-api(テストで JAX‑RS クライアントを使う場合)
  - (DB を使う場合)h2, arquillian-persistence

  注意点と選択肢
  - Arquillian は「実際のコンテナ上での統合テスト」を重視するため設定や実行に手間がかかる(コンテナの選択:WildFly/Payara 等)。軽量に始めたい場合は単体テストを Mockito + JUnit5
   で書き、後で Arquillian 統合テストを追加するのがおすすめです。
  - JUnit5 用の Arquillian 拡張を使えば JUnit5 と統合できますが、一部の古いチュートリアルは JUnit4 前提なので注意。

  次に私ができること
  - 今すぐ src/test/java/org/example/BookResourceTest.java に Arquillian ベースの統合テストの雛形を実装しましょうか?(どのアプリサーバでテストしたいか教えてください:WildFly /
  Payara / GlassFish / embedded など)
  - あるいは、まずは速く回る単体テスト(JUnit5 + Mockito + AssertJ)を先に追加して、その後で Arquillian 統合テストを追加する方が良い、という選択も可能です。

  どちらに進めますか?どのアプリサーバ/DBを使う予定か教えてください。

こちらもうまくいきました。

rulesの説明どおり、Frontmatterにpathsを書いた場合はファイルを読み込む時に一緒に読むようで、対象のソースコードについて
聞いても実際にファイルを参照しなければrulesのファイルを読むこともありませんでした。

rulesに書いた内容を読んで欲しい場合は、確実にファイルを参照させた方がよさそうですね。

おわりに

Claude CodeのCLAUDE.md、Auto memory、rulesについて調べてみて、rulesを試してみました。

rulesだけを調べるつもりだったのですが、せっかくならとCLAUDE.mdやAuto memoryについてもゆっくり見直してみました。
いい確認の機会になったと思います。