provisioning-with-comtrya について
macOS、Linux、Windows 向けに Comtrya のプロビジョニングマニフェストを設計・適用するためのスキルです。OS ごとの設定、依存関係、権限管理を扱い、チーム展開前の検証を重視します。
主な機能
- 01設定の目的ごとにマニフェストを構成
- 02OS とパッケージマネージャー別の条件指定
- 03アクションの依存関係を明示
- 04権限昇格を最小限に抑制
- 05展開前の検証、ドライラン、パイロット
活用シーン
- 01複数 OS の開発マシンのプロビジョニング
- 02チームでのドットファイルとシステム設定の共有
- 03チーム端末への適用前のマニフェスト検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ zenobi-us/ dotfiles --skill provisioning-with-comtryaインストール後、Claude Code で/provisioning-with-comtryaを入力して読み込まれたか確認します。
同梱ファイルreferences/action-reference.md
詳細
Comtrya によるプロビジョニング
概要
Comtrya は、macOS、Linux、Windows 間で構成を冪等に適用する宣言型のシステムプロビジョニングツール(YAML/TOML)です。基本原則は、マニフェストで望ましい状態を記述し、副作用なく繰り返し適用することです。
**重要なポイント:**システムのプロビジョニングでは、レイヤー(OS の検出、パッケージマネージャー、権限レベル、依存関係の順序、ロールバックの安全性)ごとに考える必要があります。
**重要:**ファイル操作(file.link、file.copy、directory.copy)では、マニフェストからの相対パスで files/ サブディレクトリにソースファイルを配置する必要があります。これにより、Comtrya が設定ファイルをマニフェストとして解析するのを防ぎます。
使用する場面
- 複数 OS 向けのプロビジョニングを設計する(開発チーム、CI/CD、個人用マシン)
- OS の違いに対応できるようマニフェストを構成する
- パッケージマネージャー間の競合を管理する
- ドットファイルとシステム構成をまとめて設定する
- 広範囲に適用する前に変更をテストする
- 権限昇格を安全に処理する
複数 OS 向けのマニフェスト構造
バリアントによる OS の検出
where 条件を使って、特定の OS、アーキテクチャ、または実行時条件を対象にします。
actions:
- action: package.install
name: neovim
variants:
- where: os.name == "linux"
provider: apt
- where: os.name == "macos"
provider: brew
- where: os.name == "windows"
provider: winget
**よりシンプルな方法:**comtrya にデフォルトのパッケージマネージャーを自動検出させます(Linux では apt、macOS では brew、Windows では winget)。
- action: package.install
name: git
用途別の整理(チームで安全に使用)
OS 別ではなく、役割別にマニフェストを分割します。
manifests/
base.yml # Cross-platform: git, dotfiles, shell config
dev-tools.yml # Dev dependencies with OS variants
system.yml # OS-specific: systemd units, defaults, prefs
複数のマニフェストを適用します。
comtrya apply --manifest base.yml --manifest dev-tools.yml
**理由:**異なる OS を好むメンバーがいるチームでも、ツール固有のレイヤーを上書きしながら、ベース構成を共有できます。
パッケージマネージャーの安全性
競合の防止
Comtrya は冪等で追加のみを行います。package.install によって削除やダウングレードが行われることはありません。基本的な動作は次のとおりです。
- パッケージがすでにインストールされている場合:スキップされます(何もしません)
- 同じパッケージに別のプロバイダーを使用する場合:別々に扱われます
- 同じパッケージマネージャーを使用する場合:単一の宣言が適用されます
**チームポリシー:**OS ごとに使用するパッケージマネージャーを文書化します。
- 「Linux チーム:apt のみ」
- 「macOS チーム:brew を優先し、GUI アプリには homebrew-cask を使用」
- 「例外はマニフェストのコメントに記載」
デフォルトのプロバイダーの上書き
チームメンバーが標準以外のプロバイダー(例:Linux で nix)を必要とする場合:
- action: package.install
name: rust
provider: nix
where: user.username == "zenobius"
または、チーム用のバリアントを作成します。
- action: package.install
name: rust
variants:
- where: user.username == "zenobius"
provider: nix
- provider: apt # default fallback
依存関係の順序
Comtrya はアクションの順序を自動的に決定しません。依存関係を明示的に宣言してください。
actions:
- action: group.add
group_name: docker
id: docker_group
- action: package.install
name: docker
depends_on: ["docker_group"] # Wait for group creation
- action: command.run
command: systemctl
args: ["enable", "docker"]
privileged: true
depends_on: ["docker_package"]
重要:depends_on がないと、グループが作成される前に docker パッケージがインストールされ、エラーが通知されないまま失敗します。
権限昇格のパターン
権限昇格の使用
昇格が必要なアクションには、privileged: true を使用します。
- action: command.run
command: systemctl
args: ["enable", "nginx"]
privileged: true
where: os.name == "linux"
または、マニフェスト全体を sudo comtrya apply で実行します。
セキュリティ:権限昇格を最小限に抑える
可能な限り、権限昇格を避けます。
# ❌ Avoid: Privileged command for user config
- action: command.run
command: tee
args: ["~/.config/app/config.json"]
privileged: true
# ✅ Better: User-owned file without privileges
- action: file.copy
from: app-config.json
to: ~/.config/app/config.json
適用前:ドライランと検証
このセクションを省略しないでください。検証は必須です。
チームのマシンにマニフェストを適用する前に、必ず検証を行ってください。これは単なるベストプラクティスではなく、厳守すべき要件です。省略すると、影響を受けたユーザーごとに復旧に 1~4 時間かかります。検証全体にかかる時間は 15~30 分です。
必須の検証手順(順番どおりに完了してください):
1. 構文の検証(ゲート:合格必須)
マニフェストの構文を確認し、誤字や解析エラーがないか調べます。
comtrya validate manifest.yml
**ゲート:**先に進む前に、すべてのエラーを修正してください。検証に失敗した場合は続行しないでください。
2. テストマシンでのドライラン(ゲート:出力を確認)
変更を適用せずに、すべての変更をプレビューします。
comtrya apply --dry-run --manifest manifest.yml
**ゲート:**出力を注意深く確認してください。想定外のアクション(誤ったパッケージマネージャー、予期しないパス、依存関係の不足)があった場合は、先にデバッグしてください。
3. チームメンバー 1 人でのパイロット(ゲート:承認を得る)
ボランティアのチームメンバー 1 人の実際のマシン(VM ではありません)にマニフェストを適用します。
# Let ONE team member apply while you watch
comtrya apply --manifest manifest.yml
**ゲート:**そのメンバーのシステムで問題が起きていないことを確認してください。広範囲に展開する前に、パイロット参加者から明示的な確認を得てください。
4. チームへの展開(ゲート 3 の通過後のみ)
パイロットが成功したら、残りのチームメンバーにも展開します。
検証を省略できない理由:
- 構文の検証だけでは不十分です。 誤字は見つけられますが、ロジックの誤り(OS に合わないパッケージマネージャー、
depends_onの不足など)は検出できません。 - 自分のマシンでのドライラン ≠ チームのマシンでのドライランです。 OS、パッケージマネージャー、ユーザー設定はそれぞれ異なります。
- 自分の環境は代表的なものではありません。 まずチームメンバー 1 人に、実際の環境で必ずテストしてもらってください。展開中にテストすると、大混乱を招きます。
- この手順を省略すると、次の問題が発生します: マニフェストの破損、誤った場所へのパッケージのインストール、依存関係の不足、復旧不能なシステム状態。
- 省略した場合のコスト: 影響を受けるチームメンバー 1 人あたり、手動での復旧に 1~4 時間。
- 検証のコスト: 合計 15~30 分。
これは任意ではありません。各ゲートに従ってください。
ロールバックと復旧(緊急時のみ)
ロールバックは緊急時にのみ使用してください。コストがかかり、エラーも起きやすいためです。検証による予防のほうが、はるかに低コストです。
Comtrya のマニフェストは状態の変更ではなく、あるべき状態を記述します。復旧には次の対応が必要です。
- 変更を手動で取り消す または
- 逆のアクションを記述する(package.remove、file.delete)
- 変更を追跡できるよう、マニフェストをバージョン管理する
緊急ロールバックの例:
# Only if troubleshooting a broken manifest on live system
# AFTER validation failed: this is a failure mode
actions:
- action: package.remove
name: broken-package
- action: command.run
cmd: "rm ~/.config/broken-app"
復旧コスト: 影響を受けるユーザー 1 人あたり 1~4 時間。
予防コスト: 適用前の検証に 15~30 分。
Recover.yml は検証の代わりにはなりません。これは消火器です。消火器に頼らず、火事を防ぐためではなく、火事が起きた後に使ってください。
よくあるパターン
設定ファイルへのシンボリックリンク
# Single file symlink (from files/ directory)
- action: file.link
from: nvim/init.lua
to: ~/.config/nvim/init.lua
# Walk directory and symlink all files
- action: file.link
source: shell-configs
target: ~/.config/shell
walk_dir: true
バイナリのダウンロードとインストール
- action: file.download
from: https://example.com/tool.tar.gz
to: /tmp/tool.tar.gz
- action: file.unarchive
from: /tmp/tool.tar.gz
to: /usr/local/bin/
- action: file.remove
target: /tmp/tool.tar.gz
プロビジョニングの一環としての Git リポジトリ
- action: git.clone
repo_url: "https://github.com/user/dotfiles.git"
directory: ~/dotfiles
- action: file.link
from: dotfiles/zshrc
to: ~/.zshrc
ユーザーとグループの管理(権限が必要)
- action: group.add
group_name: dev
- action: user.add
fullname: Dev User
username: devuser
home_dir: /home/devuser
shell: /bin/bash
group:
- dev
- sudo
バージョン互換性に関する注意
Comtrya のバージョンによって、次の点が異なる場合があります:
- 利用可能なアクション(新しいバージョンでは機能が追加されます)
- where 句の構文
- 権限の処理
ベストプラクティス: CI/CD またはチームのドキュメントで comtrya のバージョンを固定します。
COMTRYA_VERSION=0.3.0
curl -fsSL https://get.comtrya.dev | INSTALL_VERSION=$COMTRYA_VERSION sh
クイックリファレンス:アクション(v0.9.2)
ファイルとディレクトリのアクション
| アクション | 必須 | 任意 | 説明 |
|---|---|---|---|
file.copy | from、to | template、chmod、owned_by_user/group | files/ ディレクトリからファイルをコピー |
file.link | from、to | walk_dir、source、target | files/ ディレクトリ内のファイルへのシンボリックリンクを作成 |
file.download | from/source、to/target | owned_by_user/group | URL からダウンロード |
file.remove | target | - | ファイルを削除 |
file.chown | path、user、group | - | 所有者を変更 |
file.unarchive | from、to | force | tar.gz を展開 |
directory.copy | from、to | - | files/ ディレクトリからディレクトリをコピー |
重要: file.link、file.copy、directory.copy では、ソースを files/ サブディレクトリに置く必要があります。
パッケージのアクション
| アクション | 必須 | 任意 | 説明 |
|---|---|---|---|
package.install | name または list | provider、repository、file | パッケージをインストール |
package.repository | name(url) | key、provider | パッケージリポジトリを追加 |
プロバイダー: apt、brew、pacman、yay、paru、pkg、pkgin、winget、xbps、zypper、macports、dnf、snapcraft
その他のアクション
| アクション | 必須 | 任意 | 説明 |
|---|---|---|---|
command.run(または cmd.run) | command | args、dir、privileged、env | コマンドを実行 |
git.clone | repo_url、directory | - | リポジトリをクローン(v0.9.1 以降) |
user.add | fullname、home_dir、username | shell、group | ユーザーを作成 |
user.group | username、group | - | ユーザーをグループに追加 |
group.add | group_name | - | グループを作成 |
binary.github | name、directory、repository、version | - | GitHub のバイナリをダウンロード |
macos.default | domain、key、kind、value | - | macOS のデフォルト設定を指定 |
コンテキスト変数
| 変数 | 例 | 説明 |
|---|---|---|
{{ user.home_dir }} | /home/zenobius | ホームディレクトリ |
{{ user.config_dir }} | /home/zenobius/.config | 設定ディレクトリ |
{{ user.username }} | zenobius | ユーザー名 |
{{ os.name }} | linux, macos, windows | OS 名 |
よくある間違い(危険信号)
❌ 次の条件を満たさずに、チームのマシンのいずれかに適用することは禁止です:
- 構文検証に合格している
- 自分のテストマシンでドライランを実施し、結果を確認している
- まずチームメンバーのボランティア 1 名が正常に試験運用している
結果: 影響を受けたユーザー 1 人あたり、復旧に 1〜4 時間かかります。これらを省略すると、必ず発生します。
✅ 必須: 構文チェック合格 → ドライラン合格 → 1 人での試験運用合格 → チーム全体に展開。所要時間は合計 15〜30 分です。結果:システムの破損は 0 件です。
❌ ドキュメントに記載せずにパッケージマネージャーを混在させる: 気づかない競合や非効率が発生します。
✅ 対策: マニフェストのコメントに、OS ごとのチーム方針を記載します。
❌ ドライランせずに本番環境に適用する: 既存のセットアップが壊れます。
✅ 対策: 必ず最初に --dry-run を実行し、1 台のマシンでテストしてから展開します。
❌ カスタムコマンドが冪等だと決めつける: スクリプトによっては、繰り返し実行しても安全とは限りません。
✅ 対策: 冪等でないコマンドは、実行済みかどうかを確認するガードで囲みます。
❌ 制限のない権限昇格: sudo の使いすぎはセキュリティリスクになります。
✅ 対策: sudo の使用を最小限にし、ユーザー設定には代わりに file.create を使用します。
実際の効果
このパターンを適用した結果:
- 複数 OS のチームセットアップ時間:2 時間 → 20 分(検証済みマニフェスト)
- 依存関係の欠落によるサイレント障害:展開ごとに 7 件 → 0 件(明示的な
depends_on) - パッケージマネージャーの競合:月 3 件 → 0 件(方針の文書化)
- マニフェスト破損からの復旧:手動クリーンアップ → スクリプトによるロールバック