コンテンツにスキップ

インストール

rulec はランタイムも外部依存も持たない一つのバイナリで、ritsu の一部として配っています。ritsu のリリースに入っているのは、ritsu という一つのバイナリと、言語ごとにそれを指すリンクです。リンクには ritsu の言語の名前が付いていて、rulec という名前で呼ぶと rulec として動きます。リリースごとに macOS(arm64、x64)と Linux(x64、arm64)のバイナリを、それぞれの SHA-256 と一緒に ritsu のリリースのページに置いています。Linux 版は静的にリンクしてあり、macOS 版がリンクするのは、どの Mac にもあるシステムのライブラリだけです。同じバイナリを Homebrew と、.deb・.rpm のパッケージからも入れられるので、そのマシンでふだん使っている入れ方を選べます。

ritsu の最初のリリース 0.23.0 は、rulec の番号を引き継いでいます。rulec 自身のリリースは 0.22.1 までで、それを入れている人の移り方はrulec 自身のリリースから移るにあります。ソースからは、ritsu のリポジトリでビルドします(ソースから)。

Homebrew

macOS でも Linux でも使えます。

$ brew install i2y/tap/ritsu
$ rulec --version
rulec 0.23.0

ritsu と七つのリンクが PATH に入るので、rulec はこれまでどおりコマンドとして使えます。古い名前の i2y/tap/rulec も同じ formula を指しますが、Homebrew 7 では、その formula を信頼してからでないと使えません。信頼する前に brew install i2y/tap/rulec を走らせると、Refusing to load formula i2y/tap/ritsu from untrusted tap i2y/tap と言って止まります。brew trust --formula i2y/tap/ritsu のあとなら、古い名前でも ritsu が入ります。

formula が入れるのは、その環境向けのリリースのアーカイブで、SHA256SUMS の行と突き合わせてから入れます。formula はリリースのたびに書き換わります。書き換えるのは、brew が macOS と Linux の両方で実際に入れて、formula のテスト(八つの名前を全部呼びます)が通ったあとです。次のリリースは brew upgrade ritsu で入ります。

Debian・Ubuntu・Fedora・RHEL

リリースごとに、x64 と arm64 の .deb と .rpm も置いています。中身はアーカイブと同じ静的リンクのバイナリなので、依存するパッケージはありません。

$ v=0.23.0; a=amd64                  # ARM なら arm64
$ curl -fsSLO "https://github.com/i2y/ritsu/releases/download/v$v/ritsu_$v-1_$a.deb"
$ curl -fsSL "https://github.com/i2y/ritsu/releases/download/v$v/SHA256SUMS" | grep "ritsu_$v-1_$a.deb" | sha256sum -c
ritsu_0.23.0-1_amd64.deb: OK
$ sudo apt install "./ritsu_$v-1_$a.deb"
$ v=0.23.0; a=x86_64                 # ARM なら aarch64
$ curl -fsSLO "https://github.com/i2y/ritsu/releases/download/v$v/ritsu-$v-1.$a.rpm"
$ curl -fsSL "https://github.com/i2y/ritsu/releases/download/v$v/SHA256SUMS" | grep "ritsu-$v-1.$a.rpm" | sha256sum -c
ritsu-0.23.0-1.x86_64.rpm: OK
$ sudo dnf install "./ritsu-$v-1.$a.rpm"

パッケージが入れるのは、/usr/bin/ritsu と、その横の七つのリンク(/usr/bin/rulec -> ritsu など)です。rulec 自身のリリースの rulec のパッケージは、このパッケージに置き換わります。

パッケージに署名はしていません。アーカイブと同じく、SHA256SUMS の行との突き合わせが検証の全部です。パッケージのリポジトリは用意していないので、apt upgrade や dnf upgrade では新しいリリースは入りません。次のリリースも同じ手順で入れてください。

リリースのバイナリ

$ v=v0.23.0; t=aarch64-apple-darwin
$ curl -fsSLO "https://github.com/i2y/ritsu/releases/download/$v/ritsu-$v-$t.tar.gz"
$ curl -fsSL "https://github.com/i2y/ritsu/releases/download/$v/SHA256SUMS" | grep "$t" | shasum -a 256 -c
ritsu-v0.23.0-aarch64-apple-darwin.tar.gz: OK
$ tar -xzf "ritsu-$v-$t.tar.gz" -C ~/.local/bin --exclude 'LICENSE-*' --exclude THIRD_PARTY_NOTICES
$ rulec --version
rulec 0.23.0

アーカイブには、ritsu と、言語ごとにそれを指すリンク(rulec、dandori、koyomi、chobo、geas、yuen、sakai)と、二つのライセンスが、同じ階層に入っています。0.23.0 より後のリリースには、バイナリが含む他者のものの通知とライセンスの文(THIRD_PARTY_NOTICES)も入ります。リンクは相対なので、PATH にあるディレクトリに展開するだけで入ります。--exclude 'LICENSE-*' --exclude THIRD_PARTY_NOTICES を付けると、ライセンスと通知は展開しません。t は aarch64-apple-darwin・x86_64-apple-darwin・x86_64-unknown-linux-musl・aarch64-unknown-linux-musl のどれかです。Linux の二つは静的リンクなので、どのディストリビューションでも動きます。Linux では sha256sum -c を使います。走らせる前に SHA256SUMS と突き合わせる、この一行が検証の全部なので、ここは飛ばさないでください。

rulec 自身のリリースから移る

rulec は 0.22.1 まで、自分のリリースを出していました。ritsu のリリースは rulec をリンクとして持つので、移って変わるのは入っているものの名前で、コマンドは変わりません。

Homebrew では、tap が formula の名前を rulec から ritsu に変えたので、brew が、入っている rulec を ritsu に移せます。Homebrew 7 は、公式以外の tap の formula を、その tap を信頼するまで読みません。tap の名前ごと formula を指定して入れると、その tap を信頼したことになります。そのとき brew install は、rulec がすでに入っていて、まだ移していないと警告します。brew migrate ritsu で ritsu に移し、brew upgrade ritsu で 0.23.0 に上げます。

$ brew install i2y/tap/ritsu
$ brew migrate ritsu
$ brew upgrade ritsu
$ rulec --version
rulec 0.23.0

brew trust --formula i2y/tap/ritsu のあとに brew upgrade を走らせても同じです。brew upgrade が、移すことと 0.23.0 に上げることを一度にします。

ritsu の .deb か .rpm を上の手順で入れると、rulec のパッケージは取り除かれ、/usr/bin/rulec は ritsu を指すリンクになります。アーカイブで入れていたなら、古い rulec があるディレクトリに ritsu のアーカイブを展開すると、古いバイナリがリンクに置き換わります。CI では、uses: i2y/rulec@v0.22.1 の行が uses: i2y/ritsu@v0.23.0 になります(CI に置く)。

ソースから

新しめの stable な Rust で、ritsu のリポジトリから入れます。

$ cargo install --git https://github.com/i2y/ritsu --locked rulec

これで rulec だけがビルドされます。rulec はほかの言語を使わず、標準ライブラリの外に依存を一つも持たないので、何も取りに行きません。パッケージを rulec ではなく ritsu にすると、ritsu と ritsu の全部の言語が入り、このサイトのコマンドは全部 ritsu rulec <コマンド> で使えます。入力の範囲を koyomi の日付からとる規則(range from koyomi)は、ritsu rulec check で検査します。

ビルドディレクトリから直接動かすなら:

$ git clone https://github.com/i2y/ritsu
$ cd ritsu
$ cargo build --release -p rulec
$ ./target/release/rulec --help

ほかに要るもの

検査には何も要りません。rulec check・fmt・gen・vectors・coverage・doc・api・explain・schema・adapter・fixtures lint は全部これ一つで完結します。

外に出るのは二つだけです。

  • rulec test — 生成した Python・TypeScript・JavaScript・Rust・Ruby・PHP・Go・Swift・Java・SQL・Wasm・NumPy を実際に走らせて、参照評価器(rulec の中にある「正解」の実装)と突き合わせます。python3・node・rustc・ruby・go・swiftc が要ります(SQL は同じ python3 の中の sqlite3 で走ります)。無ければ「どれを飛ばしたか」を言って、落ちはしません。
  • rulec verify — アダプタを子プロセスとして起動するので、そのアダプタを書いた言語が要ります。

生成物を型検査したい場合だけ、さらにツールが要ります。生成 Python は mypy --strict を、生成 TypeScript は tsc --strict を通り、生成 Ruby には steep が読む .rbs が付いてきます。どれも使うのに必要ではありません — 生成物はそれ自体でそのまま動きます。

エージェントスキル

rulec を実際に使うのはたいていエージェントです。skills/rulec/(ritsu のリポジトリの根)は、そのためのスキルです。

入っているのは、作業の手順、文法、検査を通る規則が十八本、データの形式、それと対応していない言語へ生成するやり方です。ツールの仕様をスキルに転記してはいません。--help と --format json と rulec explain で rulec 本体に聞くように書いてあるので、インストールしてあるバイナリが新しくなっても古びません。

ritsu のバイナリが、ritsu とほかの言語のスキルと一緒に持っています。

$ ritsu skills install rulec

.claude/skills/rulec/ の下に SKILL.md と六つのファイルが置かれます。フォルダの名前でスキルが見つかるので、中身をばらして置かないでください。一つのプロジェクトではなく全部で使うなら、--user を付けて ~/.claude/skills/ に置きます。--dir <dir> を付けると、ほかのエージェントがスキルを読む場所に置きます。Claude Code なら、プラグイン ritsu に八つのスキルが入っています(/plugin marketplace add https://i2y.github.io/ritsu/marketplace.json のあと /plugin install ritsu@ritsu)。リポジトリのクローンから skills/rulec をコピーしても同じで、リリースごとの ritsu-skills-v<版>.zip にも八つが入っています。

要るのは rulec が PATH にあることだけです(上のどの入れ方でも構いません)。

あとは「この運賃表から .rule を書いて」「この E101 を直して」のように頼めば、たいていはスキルが自動で使われます。確実に使わせたいときは「rulec のスキルを使って」と名指しで頼んでください。

MCP サーバ

エージェントにシェルが無いとき(チャットの画面、MCP で話す IDE の補助)は、同じコマンドがツールとして使えます。

$ claude mcp add rulec -- rulec mcp

どのクライアントでも、コマンドが rulec mcp の stdio サーバとして登録できます。

{ "mcpServers": { "rulec": { "command": "rulec", "args": ["mcp"] } } }

コマンド一つがツール一つ(rulec_check、rulec_gen、rulec_doc …)、フラグ一つが引数一つで、結果の最後に exit code が付きます。手順書とリファレンスはリソースとして出るので、このリポジトリを読めないエージェントでも、まず rulec://docs/agents.md を読めます。形は形式にあります。

こちらは stdio だけです。 渡しているのはファイルを読み書きするコマンドそのものなので、シェルの代わりとして同じマシンに置くものです。--http はありません。これは足りないのではなく、そう決めています。

MCP サーバはもう一つあって、そちらは別物です。 ここまでは規則を書くエージェントのためのツールでした。規則を呼ぶエージェントには、gen が規則そのものをサーバとしてモジュールの隣に書きます。そちらは stdio と、MCP の Streamable HTTP(--http 8000)の両方を話します。URL しか受け付けない相手のためです。MCP Apps を表示できるホストには、人が読むページをそのツールの view としても渡します: 規則をエージェントのツールにする。

言語

出力の既定は英語です。設定は一つで、生成コードの中の文面まで含めて、出るものが全部日本語になります。

$ rulec check rules/送料.rule --lang ja
$ RULEC_LANG=ja rulec check rules/送料.rule

優先順位は --lang → RULEC_LANG → RITSU_LANG → 既定。システムのロケールは見ません。 生成物は gen --check で照合され、CI のログは diff されるので、走らせたマシンで出力が変わってはいけないからです。

CI に置く

uses: i2y/ritsu@v0.23.0 の一行で、そのリリースの ritsu が検査済みで runner の PATH に入ります。rulec などのリンクも一緒です。action を指す ref がそのままリリースなので、既定では二つがずれません(別のリリースを入れたいときだけ with: { version: … } で明示します)。SHA256SUMS との突き合わせは必ず走ります — その行が無いだけでも落ちます。アーカイブのハッシュを workflow 側にも書いて固定したいなら、with: { sha256: … } を足します。検査が一つ増えます。rulec 自身の最後のリリースを指す uses: i2y/rulec@v0.22.1 も、rulec のリポジトリが残っているあいだは動きます。

入れるのに要るのはその一行だけですが、その前に actions/checkout が要ります — rulec が読むのは、あなたのリポジトリの rules/ だからです。ジョブ全体ではこうなります。

check:
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@v7
      with:
        fetch-depth: 0                   # --diff-base が origin/main を読む
    - uses: i2y/ritsu@v0.23.0
    - run: rulec fmt --check rules/
    - run: rulec check rules/ --diff-base origin/main
    - run: rulec gen rules/ --out generated/ --check
    - run: rulec coverage rules/
    - run: rulec test generated/

走るのは Linux(x86_64 / aarch64)と macOS(x86_64 / arm64)の runner です。リリースがその四つしか無いので、ほかの runner では no ritsu release is built for … と言って止まります。

この五つの run: がゲートです。過去再生は記録を持つ環境の別ジョブにします。変更が目に見えるのはこちらで、PR に「何件がいくら動くか」のコメントが付きます。わざとそうしている所が四つあります。

  • 旧の版は rules/送料.rule@origin/main、つまり base ブランチにあるままのファイルです。checkout でそのブランチを取ってきておきます。
  • diff は影響があると exit 1 を返します。ここではそれは失敗ではなく情報なので、1 では先へ進み、2 でだけ止めます。
  • --terse は入力例の列を出しません。コメントはリポジトリを読める全員が見るもので、本番の記録の値を置く場所ではないからです。
  • 文面の言語は、その PR を読む人の言語にします。貼る先がそこだからです。
replay:
  if: github.event_name == 'pull_request'
  runs-on: ubuntu-latest
  permissions:
    contents: read
    pull-requests: write
  steps:
    - uses: actions/checkout@v7
      with:
        fetch-depth: 0                   # 旧の版は origin/main から読む
    - uses: i2y/ritsu@v0.23.0
    # 記録を $FIXTURES に置くところはご自身で: アーティファクトか、権限を絞った保管先から
    - run: rulec diff rules/送料.rule@origin/main rules/送料.rule --fixtures "$FIXTURES" --format markdown --terse > diff.md || [ $? -eq 1 ]
      env:
        RULEC_LANG: ja
    - run: gh pr comment "$PR" --body-file diff.md
      env:
        GH_TOKEN: ${{ github.token }}
        PR: ${{ github.event.pull_request.number }}

上のジョブは記録が要ります。下のジョブは二つの版だけで走るので、初日から PR ごとに回せます。コメントは二つ並べて読むものです——何が動きうるかと、手元の記録のうち何件が動くか。

- run: rulec diff rules/送料.rule@origin/main rules/送料.rule --format markdown > region.md || [ $? -eq 1 ]
  env:
    RULEC_LANG: ja
- run: gh pr comment "$PR" --body-file region.md

規則が複数あるなら、git diff --name-only --diff-filter=M origin/main...HEAD -- 'rules/*.rule' がこの PR で変わったものを並べるので、同じ二行を規則ごとに回します。

次に読むもの