📚

VibeCodingに必須の便利ツール「repomix」の紹介

に公開

repomixとは

repomixとはLLMに渡すためのコードコンテキストを1つのファイルにまとめてくれるツールです。yamadashy (やまだし)さんによって制作されており、ご本人のZenn記事も公開されています。
https://github.com/yamadashy/repomix
https://zenn.dev/yamadashy/articles/ai-tool-repomix-5000-star
最近ではOpen Source Awards 2025のPowered by AI部門にもノミネートされているホットなツールです。
https://x.com/repomix_ai/status/1925895219523846415

なぜVibeCodingにrepomixを使うのか

VibeCodingにおいて実装計画を作成するのは必須です。実装計画を作成せずに自ら実装の指示プロンプトを考えるのは骨が折れますし、ハルシネーションが起きやすく、本当にやってほしい実装から外れたコードを生成されることが多くあります。
実際ClineではPlanモードという機能が実装されており、推論モデルにやりたい実装を計画させてから実装するフローが推奨されています
この実装計画の作成にあたってはどれだけ質の高いコンテキストをLLMに与えられるかが重要です。質の高いコンテキストとは、実装を行うための必要最低限な情報であり、必要以上の情報を与えすぎても、逆に少なすぎてもLLMはハルシネーションを起こしやすくなってしまいます。この必要最低限な情報をまとめるのにrepomixが効果を発揮してくれます。

repomixの使い方

実際に使い方を知るとイメージしやすいので説明します。
例として自作のブログにページネーション機能を実装してみます。(テスト実装なのでデプロイはしません)
下記画像の記事リンクの下にページネーションコンポーネントを配置するイメージです。

インストール

nodeがインストールされている環境なら以下コマンドですぐに使えます。

npx repomix

それ以外ならグローバル環境にインストールすることで使えるようになります。

# Install using npm
npm install -g repomix

# Alternatively using yarn
yarn global add repomix

# Alternatively using Homebrew (macOS/Linux)
brew install repomix

# Then run in any project directory
repomix

コンテキストをまとめる

以下のコマンドを打ってコードの情報を1ファイルにまとめます。

repomix --include src/pages/index.astro,src/constants,package.json,

それぞれのファイルの概要は以下です。

ファイル 概要
src/pages/index.astro ページネーション機能を実装したいファイル
src/constants ブログで使う定数ファイルを定義しているディレクトリ。1ページに表示する記事リンクの最大数をここで管理しているので指定
package.json いわずもがな。指定しておくとエージェントが使っているパッケージマネージャーやライブラリを理解してくれるので指定

するとrepomix-output.ymlというファイルが生成されます。中身は以下のようになっています。

repomix-output.yml
This file is a merged representation of a subset of the codebase, containing specifically included files, combined into a single document by Repomix.

<file_summary>
This section contains a summary of this file.

<purpose>
This file contains a packed representation of the entire repository's contents.
It is designed to be easily consumable by AI systems for analysis, code review,
or other automated processes.
</purpose>

<file_format>
The content is organized as follows:
1. This summary section
2. Repository information
3. Directory structure
4. Repository files (if enabled)
5. Multiple file entries, each consisting of:
  - File path as an attribute
  - Full contents of the file
</file_format>

<usage_guidelines>
- This file should be treated as read-only. Any changes should be made to the
  original repository files, not this packed version.
- When processing this file, use the file path to distinguish
  between different files in the repository.
- Be aware that this file may contain sensitive information. Handle it with
  the same level of security as you would the original repository.
</usage_guidelines>

<notes>
- Some files may have been excluded based on .gitignore rules and Repomix's configuration
- Binary files are not included in this packed representation. Please refer to the Repository Structure section for a complete list of file paths, including binary files
- Only files matching these patterns are included: src/pages/index.astro, package.json, src/constants
- Files matching patterns in .gitignore are excluded
- Files matching default ignore patterns are excluded
- Files are sorted by Git change count (files with more changes are at the bottom)
</notes>

</file_summary>

<directory_structure>
package.json
src/constants/common.ts
src/pages/index.astro
</directory_structure>

<files>
This section contains the contents of the repository's files.

<file path="src/constants/common.ts">
export const PAGE_SIZE = 2;
</file>

<file path="package.json">
{
  "name": "blog-app",
  "type": "module",
  "version": "0.0.1",
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
    "build": "astro check && astro build",
    "preview": "astro preview",
    "astro": "astro",
    "format": "prettier --write src/"
  },
  "dependencies": {
    "@astrojs/mdx": "^4.0.7",
    "@astrojs/react": "4.1.6",
    "@astrojs/rss": "^4.0.11",
    "@astrojs/sitemap": "^3.2.1",
    "@radix-ui/react-slot": "^1.2.2",
    "@tailwindcss/vite": "^4.1.6",
    "astro": "^5.1.9",
    "astro-icon": "1.1.1",
    "astro-seo": "^0.8.4",
    "class-variance-authority": "^0.7.1",
    "clsx": "^2.1.1",
    "date-fns": "^3.6.0",
    "lucide-react": "^0.509.0",
    "react": "18.3.1",
    "react-dom": "18.3.1",
    "remark-directive": "^3.0.0",
    "satori": "^0.10.14",
    "sharp": "^0.33.5",
    "tailwind-merge": "^3.2.0",
    "tailwindcss": "4.1.6",
    "tailwindcss-animate": "^1.0.7"
  },
  "devDependencies": {
    "@astrojs/check": "^0.9.4",
    "@tailwindcss/typography": "^0.5.15",
    "@twemoji/api": "^15.1.0",
    "@twemoji/parser": "^15.1.1",
    "@types/mdast": "^4.0.4",
    "@types/react": "18.3.5",
    "@types/react-dom": "18.3.0",
    "@types/sharp": "^0.32.0",
    "lefthook": "^1.7.14",
    "mdast-util-directive": "^3.0.0",
    "prettier": "^3.3.3",
    "prettier-plugin-astro": "^0.14.1",
    "tw-animate-css": "^1.2.9",
    "typescript": "^5.5.4",
    "unist-util-visit": "^5.0.0"
  }
}
</file>

<file path="src/pages/index.astro">
---
import { getCollection } from "astro:content";
import BaseLayout from "../layouts/BaseLayout.astro";
import Profile from "../components/Profile.astro";
import Tags from "../components/Tags.astro";
import PostPreview from "../components/PostPreview.astro";
import { PAGE_SIZE } from "../constants/common";

const posts = (await getCollection("blog"))
  .sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime())
  .slice(0, PAGE_SIZE);
const uniqueTags = [...new Set(posts.map((post) => post.data.tags).flat())];
---

<BaseLayout title="Cryptobox Tech Blog">
  <div class="sm:grid sm:grid-cols-[70%_1fr] sm:gap-4 my-4">
    <div class="flex flex-col gap-4 mx-4 sm:mx-auto">
      {
        posts.map((post) => (
          <PostPreview
            post={post}
            blogLinkPrefix="blog/"
            tagLinkPrefix="tags/"
          />
        ))
      }
      <Tags class="sm:hidden flex" tags={uniqueTags} />
      <Profile class="sm:hidden flex" />
    </div>
    <div>
      <Profile class="hidden sm:flex" />
      <Tags class="hidden sm:flex mt-4" tags={uniqueTags} />
    </div>
  </div>
</BaseLayout>
</file>

</files>

好みの推論モデルにこれをコピペしてかつ、やりたいこと記述して実装計画を作成させます。今回はo3を使いました。

// repomix-output.ymlの中身をコピペ
---
src/pages/index.astroにページネーション機能を実装する計画書を作成して。ページネーションコンポーネントはshadcnのものを使ってPostPreviewの下に配置するようにして。
またディレクトリ構成は以下なので参考にして
---
// tree -L 2 src した結果をコピペ

すると以下のような実装計画書を生成してくれました。

o3が生成した実装計画
# **`src/pages/index.astro` ページネーション実装計画書**

## 1. 目的

* 投稿一覧ページにページネーションを導入し、**UX の向上**と**ビルドサイズの削減**を図る。
* shadcn/ui のコンポーネントを用い、既存サイトの配色・トーン & マナーと統一する。

---

## 2. 現状整理

| 項目     | 現状                                                           |
| ------ | ------------------------------------------------------------ |
| ルーティング | ルート `/` に `index.astro` が配置され、最新 2 件のみ表示 ( `PAGE_SIZE = 2` ) |
| 一覧表示   | `<PostPreview>` をループで描画                                      |
| スタイル   | Tailwind + shadcn/ui を混在利用 (色は Theme Token 依存)               |
| データソース | `astro:content` の blog コレクション                                |

---

## 3. 要件

1. **ページネーション機能**

   * 1 ページあたりの表示件数を **8 件**に拡張 ( `PAGE_SIZE = 8` とする)。
   * 2 ページ目以降は `/page/2`, `/page/3` … の静的ルートで配信。
   * **SEO 対応**のため、`rel="canonical"` と `rel="prev|next"` を適切に出力。
2. **UI コンポーネント**

   * shadcn/ui の `<Pagination>` を流用し、`class="mt-8"` で `<PostPreview>` の直下に配置。
   * カラーパレットは `text-primary` / `bg-secondary` など既存ユーティリティを使用して統一。
3. **アクセシビリティ**

   * ボタンは `aria-label` を設定。
   * キーボードフォーカスリングを明示。
4. **テスト**

   * ページ数が正しく計算されるユニットテスト。
   * ビルド後、`/page/N` がすべて生成される e2e テスト (Playwright)。

---

## 4. ディレクトリ/ファイル設計

src/
├─ components/
│ └─ Pagination.tsx ← 追加 (shadcn/ui ラッパー)
├─ pages/
│ ├─ index.astro ← 1 ページ目用 (page = 1)
│ └─ page/[page].astro ← 動的ルート (2 ページ目以降)
└─ constants/
└─ common.ts ← PAGE_SIZE = 8 へ変更


---

## 5. 実装ステップ

1. **定数の更新**

   ```ts
   // src/constants/common.ts
   export const PAGE_SIZE = 8;
  1. Pagination コンポーネント作成

    • src/components/Pagination.tsx に以下を新規作成。

      import { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationPrevious, PaginationNext } from "@/components/ui/pagination";
      import { cn } from "class-variance-authority";
      
      interface Props { current: number; total: number; basePath?: string }
      export default function Paginator({ current, total, basePath = "" }: Props) {
        const pages = Array.from({ length: total }, (_, i) => i + 1);
        return (
          <Pagination className="mt-8">
            <PaginationContent>
              <PaginationPrevious href={`${basePath}/${current - 1}`} disabled={current === 1} />
              {pages.map((p) => (
                <PaginationItem key={p}>
                  <PaginationLink href={`${basePath}/${p}`} isActive={p === current}>
                    {p}
                  </PaginationLink>
                </PaginationItem>
              ))}
              <PaginationNext href={`${basePath}/${current + 1}`} disabled={current === total} />
            </PaginationContent>
          </Pagination>
        );
      }
      
    • shadcn/ui の pagination コンポーネントを npx shadcn-ui@latest add pagination で追加すると依存 CSS/TSX が生成される。

  2. index.astro の調整

    1. Astro.url.pathname からページ番号を取得 (const page = Number(Astro.url.searchParams.get("page") ?? 1) など)。
    2. 投稿の オフセット最大件数を計算。
    3. <Paginator><PostPreview> リストの下に配置。
  3. page/[page].astro の作成

    • src/pages/page/[page].astroindex.astro と同ロジックで複製し、page パラメータを props から取得。
    • getStaticPaths で総ページ数分の静的ルートを生成。
  4. SEO タグ

    • BaseHead.astro に以下を追加:

      <link rel="canonical" href={Astro.site.origin + (page === 1 ? "/" : `/page/${page}`)} />
      {page > 1 && <link rel="prev" href={page === 2 ? "/" : `/page/${page - 1}`} />}
      {page < totalPages && <link rel="next" href={`/page/${page + 1}`} />}
      
  5. テスト/ビルド確認

    • pnpm builddist/page/N/index.html が生成されること。
    • Playwright でページ遷移の a11y および表示件数を確認。

6. スケジュール (目安)

日付 タスク
05/26 コンポーネント追加・定数更新
05/27 index.astro & page/[page].astro 実装
05/28 SEO タグ & テストコード追加
05/29 コードレビュー & リファクタリング
05/30 本番環境デプロイ

7. 留意事項

  • shadcn/ui の Theme は Tailwind の :root 変数を参照しており、既存配色と自然に統合可能。
  • オープングラフ画像生成ロジックを修正する場合は OgImage.tsx も更新が必要。
  • 投稿が 0 件のページには 404 を返し、robots で noindex を指定する。

以上。

これをそのままCursorなりCopilotAgentなりお好みのエージェントに渡して、「上記の指示書に従って実装してください」と命令します。今回はCursorでモデルはClaude Sonnet 4を使用しました。

すると以下のように想定通りにページネーションコンポーネントが配置され、機能も問題なく実装されました。

本当にrepomixは必要か

しかし、わざわざrepomixを使わなくてもCursorやCopilotAgentの「Add Context」を使ってコンテキストを与え、ASKモードで実装計画を作らせればいいと思うかもしれません。自分もそう思って画像のようにコンテキストを与えて実装計画を作らせていたのですが、与えるコンテキストが多くなるにつれて、全てを読んでくれず無視される場面に多く遭遇しました。

理由は不明ですが、ある一定規模以上の実装になると生成される計画書の質が目に見えて悪くなってしまったのです。一方repomixを使ってコンテキストを与えた場合は、読み飛ばしをされることがほとんどなく、質の高いアウトプットを出してくれることが多いです。

また、repomixを使う利点は他にもあります。

モデル本来の力を使える

例えばGemini 2.5 Proは100万トークンのコンテキストウィンドウに対応していますが、copilot上で使うと64k程度に制限されており本来の力を発揮できません。repomixを使えばブラウザのgeminiを使えるため、フルで力を発揮させたうえで実装計画を作ることができます。

最新のモデルがいち早く使える

最新のモデルが発表されてからCursorやCopilot上で使えるようになるには、多少のタイムラグがあります。repomixを使えばIDEのアップデートを待たずとも、すぐにモデルを使うことができるので便利です。

別リポジトリのコンテキストを与えることができる

例えばOpenAPIのスキーマを記述しているアプリとは別のリポジトリの情報も与えつつ実装計画を作成したいときに、repomixで情報をまとめて渡せるので便利です。また、別リポジトリの一部のディレクトリの情報だけ渡すといった、LLMに渡すべきコンテキストを柔軟に取捨選択しつつ与えられる部分が気に入っています。

おわりに

簡単な紹介になってしまい大変恐縮ですが、便利なのに周りで使っている方があまりいなかったため記事にしてみました。少しでも興味を持っていただけたなら幸いです。ぜひ使ってみてください。

Discussion