git worktreeの不満を解消するためにCLIツールを自作した
この記事について
こんにちは、Progate Prospects / Path のエンジニアをしている @708u です。
近年のClaude Codeを始めとするcoding agentを使った開発では、複数の作業を並列で進めるためにgit worktreeを活用する場面が増えてきます。開発フロー内でworktreeを使ううちにいくつかの課題を感じ、それを解決するためにtwigというCLIツールを作りました。
この記事ではtwigの紹介と、開発を通じて得た知見を共有します。
git worktreeとは
git worktreeの基本的な概念を簡単に整理します。
branchは作業内容を分離する概念です。通常の開発では、1つのディレクトリで複数のbranchを切り替えながら作業します。一方、worktreeは作業ディレクトリそのものを分離する仕組みです。worktreeを使うと、複数のディレクトリで同時に異なるbranchを扱えます。
Claude Codeなどのcoding agentと相性が良い理由は、複数の作業を並列で進められるからです。
あるworktreeで作業しながら、別のworktreeで実装を進める、といった使い方ができます。
git worktreeの課題
git worktreeを使い始めて、いくつかの課題に気づきました。
gitignoreのファイルが引き継がれない
git worktreeを使い始めて最初に気づいた課題は、gitignoreに指定したファイルが新しいworktreeに引き継がれないことでした。Claude Codeのsettings.local.jsonなど、個人設定を毎回手動でコピーする必要があり、これが地味に手間でした。
派生worktree上から新しいworktreeを作成しづらい
feat/a上で作業中に新しいタスクを思いついたとします。feat/bを作りたいのですが、feat/a上でgit worktree addを実行すると、feat/aベースで作成されてしまいます。mainベースで新しい作業を始めたい場合、わざわざmainのworktreeに移動する必要がありました。そして、この手間が面倒で結局思いついたアイディアをやらずに忘れてしまうということが何度もありました。
コマンドが長い
branchとworktreeを同時に作成する場合、git worktree add -b feat/new ../repo-worktree/feat/new mainのように、指定する項目が多くなります。branch名、worktreeのパス、ベースブランチをすべて指定する必要があります。
不要なworktreeの削除が面倒
PRをマージした後、リモートブランチは自動削除されますが、ローカルのworktreeとbranchは残ります。削除するにはgit worktree removeとgit branch -dを個別に実行する必要があります。worktreeが複数溜まってくると、どれが削除可能かを一つずつ確認するのが面倒でした。
これらの課題はClaude Codeに依頼することで解消することはできるのですが、シンプルな操作で解決できるのであれば自分でコマンド実行したほうが早いです。また、自然言語で指示を与えると、必ずしも処理が成功するわけではなく、複数コマンドの実行とcoding agentの思考時間を含めると、いくらか時間がかかります。
上記の問題を解決するために、何か便利なツールがほしいな、と思い始めました。
なぜ新しく作ったのか
新しくツールを作った理由は2つあります。
1つ目は、Claude Codeで一からツールを作る体験をしたかったからです。普段の仕事ではClaude Codeを既存の中規模repoに適用することが主でした。coding agentを用いて一からツールを設計・実装する体験をしていなかったのです。年末年始に何かやろうと思っていたタイミングで、ちょうど課題感を感じていました。
2つ目は、既存ツールと自分の求める方向性が違っていたからです。車輪の再発明は避けたかったので、まず既存ツールを調べました。すると以下の2つが候補に上がりました。
wtp
wtpはcdやpre run/post runなど、worktree周辺の操作も含めて統合的にサポートしています。個人的には、worktreeとbranchの抽象化に特化して、周辺操作はshellで自由に組み合わせられる方が好みでした。
git-wt
git-wtはgit wtのようにgitのサブコマンドのように動作する設計になっています。私としては、gitとは別のレイヤーとして動作するツールが欲しいと感じていました。また、git-wtはworktree作成時にuntrackedなどを個別に指定できるオプションがあります。gitコマンドの拡張という思想では妥当な設計ですが、自分の開発スタイルでは区別が必要な場面がほとんどありませんでした。どちらかというと、多くのユースケースを意識せずカバーできるインターフェースがより好みでした。
どちらも優れたツールですが、私が求めていた方向性とは少し違っていました。
こうした経緯から、思いついた勢いに任せて自分の思想を反映したツールとして、twigを作ることにしました。
余談ですが、twigという名前には2つの由来があります。worktreeから派生した小枝という意味と、git worktreeの頭文字gwtのアナグラムです。
この記事を公開した時点で私が存じていなかったのですが、gwqというgit worktree管理のツールがあるようです。
gwqも解決したい問題感は同じように見えており、worktreeとbranch管理をシンプルなインターフェースで行えるようです。また上記2つのツールとの差分として、以下が挙げられそうです。
- TUIツールライクなfuzzy finder機能
- tmuxとのintegration機能
ghqやfzfを組み合わせながら、coding agentとtmuxを併用してより効率的な開発を進めたい方におすすめできそうです。
ただし、上記でも触れているように、twigの責務はbranchとworktreeの管理のみを主としたく、その点において差別化はあるのかな、と感じました。
設計思想
twigの設計思想を大きく4つ紹介します。
branchとworktreeを1つの概念として扱う
twig add feat/xでworktreeとbranchを同時に作成します。twig remove feat/xでworktreeとbranchを同時に削除します。開発者は「作業単位」として捉えればよく、worktreeとbranchを別々に管理する必要がありません。
gitの機能を逸脱しない
pre run / post runなどの拡張機能は、呼び出し側でshellを書くことで実現できます。twigはgitの機能範囲内で動作します。ただしsymlinkはgitの標準機能外ですが、twigで提供したい要素として例外的に扱っています。submodule初期化もgitの機能群の一つとして扱っています。
ユースケースの抽象化を提供する
gitの最小操作単位ではなく、よく使う操作を抽象化しています。例として後述する--carryオプションがあります。untrackedもindexedも区別せず、全ての差分を移動対象とします。実際のユースケースでは区別することがほとんどないためです。
人間とAI両方が使いやすいインターフェース
-qオプションで標準出力をworktreeのフルパスのみにできます。エンジニアはshellでpipeや変数展開を使って自由に処理をかけられます。Claude Codeは確認コマンドなしで出力を受け取り、後続処理を能動的に行えます。
UNIX哲学に則り、できる限りコマンド同士が連携しやすい設計を心掛けています。「1つのことをうまくやる」「テキストストリームで連携する」という原則です。twigは worktree/branch管理に特化し、出力はパイプやサブシェルで他のコマンドと組み合わせられます。
# 作成したworktreeに即座に移動
cd $(twig add feat/new -q)
# 作成後に依存関係をインストール
(cd $(twig add feat/new -q) && npm i)
# 全worktreeでgit fetchを実行
twig list -q | xargs -I {} git -C {} fetch
# fzfで選択したworktreeに移動
cd $(twig list -q | fzf)
前のセクションで触れたpre run / post runは、このようにシェルの組み合わせで実現できます。
現在はClaude Codeを使っていますが、他のcoding agentに乗り換えてもそのまま利用できることを目指しています。特定のツールに依存しない、汎用的なCLIインターフェースです。
インストール
ここからは主要機能を紹介します。手元で試しながら読みたい方はインストールしてください。
# Homebrew
brew install 708u/tap/twig
# Go
go install github.com/708u/twig/cmd/twig@latest
主要機能
worktreeの作成
twig addはworktreeとbranchを同時に作成します。gitではgit worktree add -b feat/new ../path/feat/new mainのように長いコマンドが必要ですが、twigでは以下のように書けます。
# 新しいworktreeとbranchを作成
twig add feat/new-feature
# 作成したworktreeに移動
cd $(twig add feat/x -q)
worktreeの作成先は設定ファイルのworktree_destination_base_dirで指定できます。設定しておくと、branch名から自動的に作成先パスが決まるため、毎回パスを指定する必要がありません。branchが既に存在する場合はそのbranchを使用し、存在しない場合は新しいbranchを作成します。
symlinkの自動作成
gitignoreのファイルが新しいworktreeに引き継がれない問題を解決します。
# プロジェクト共有
symlinks = [".envrc", ".tool-versions"]
# 個人設定、gitignore対象
extra_symlinks = [
".claude/user_instructions/some/file.md",
"scripts/personal",
]
twig add feat/new # 設定に基づいてsymlinkが自動作成される
コピーではなくsymlinkにする理由は2つあります。1つ目はコピーコストを下げることです。2つ目は設定ファイルへの変更をmain側と共有できることです。Claude Codeを動かしていると、都度新しくAllowしたくなるコマンドやToolがしばしばあると思います。symlinkで共有することで、全てのworktreeで同じ設定を共有することが可能になります。
また、プロジェクト共有の設定と個人設定を分けることで、チームメンバーに影響を与えずに自分の環境をカスタマイズできます。
どこからでもmainから分岐する
派生worktreeから新しいworktreeを作ると派生元ベースになる問題を解決します。
default_source = "main"
# feat/a上で実行してもmainベースで作成される
twig add feat/new
# --sourceで明示的に上書きも可能
twig add feat/new --source develop
どのworktreeにいても、常に指定したブランチから新しいworktreeを作成できます。派生worktree上で新しいタスクを思いついても、mainベースで作業を始められます。
submoduleの自動初期化
submoduleを含むリポジトリでは、worktree作成時に自動で初期化できます。
init_submodules = true
# --init-submodulesフラグでも指定可能
twig add feat/new --init-submodules
設定ファイルで有効にしておくと、毎回フラグを指定する必要がありません。submodule初期化が失敗しても警告を表示するだけでworktree作成は成功します。submoduleサーバーが一時的に利用できない場合でも、worktreeは使えます。
--submodule-referenceを指定すると、main worktreeのsubmoduleオブジェクトを再利用します。remoteからfetchせずに済むため、大きなsubmoduleの初期化時間を短縮できます。
submodule_reference = true
# フラグでも指定可能
twig add feat/new --init-submodules --submodule-reference
--carryオプション
作業中の変更を新しいworktreeに移動します。元のworktreeはcleanになります。
# 作業中の変更を新しいworktreeに移動
twig add feat/refactor --carry
# 別のworktreeから変更を持ってくる
twig add feat/new --carry=feat/old
--fileオプションで特定ファイルのみcarryできます。
# 計画書だけを新しいworktreeに移動
twig add feat/impl --carry --file "docs/plan.md"
# Goファイルのみを移動(globstar対応)
twig add feat/refactor --carry --file "**/*.go"
carryの具体的なユースケースを説明します。main worktreeでClaude Codeの/planを使って計画を立てているとします。作成された計画書(mdファイル)は、基本的にはその計画に則って実装開始すると思います。ここで、計画書を新しいworktreeにcarryして、そこでClaude Codeを起動して実装を開始します。main worktreeには計画書が残らないため、cleanなまま次の計画を立てられます。複数の計画を並行して進めるワークフローに適しています。
clean による不要なworktreeの一括削除
一般的に削除可能とみなせるworktreeを自動検出して一括削除します。マージ済みのブランチ、リモートで削除されたブランチ(upstream gone)、ディレクトリが外部で削除されたworktreeなどが対象です。私が最も頻繁に手動で実行するコマンドです。特に並列作業用にworktreeをバシバシ作成していると、気づくと削除対象のworktreeが10個以上溜まっていることもザラにあります。一括で不要とみなせるものを消せるのは便利です。
# 削除候補を確認
twig clean --check
# 確認プロンプト付きで削除
twig clean
# 確認なしで削除
twig clean --yes
出力例を示します。
clean:
feat/old-branch (merged)
fix/completed (upstream gone)
Proceed? [y/N]:
安全性チェックの詳細
以下の条件をすべて満たすworktreeのみ削除対象になります。
| 条件 | 説明 |
|---|---|
| マージ済み | ターゲットブランチにマージされている、またはupstreamが削除されている |
| 変更なし | 未コミットの変更がない |
| submodule変更なし | submoduleに未コミットの変更がない |
| ロックされていない | worktreeがロックされていない |
| カレントでない | 現在のディレクトリではない |
| mainでない | mainのworktreeではない |
upstream gone検出
PRでsquash/rebaseマージ後、リモートブランチが削除されます。twigはこれを「upstream gone」として検出します。--forceなしで削除可能です。
| マージタイプ | 検出方法 | 検出可否 |
|---|---|---|
マージコミット(--no-ff) |
git branch --merged |
可 |
| squashマージ(PR) | upstream gone | 可 |
| rebaseマージ(PR) | upstream gone | 可 |
submoduleの安全な扱い
gitのgit worktree removeは、submoduleが初期化されているだけで--forceが必要になります。twigはsubmoduleに未コミットの変更があるかを確認します。変更がなければ--forceなしで削除できます。変更がある場合のみ削除をブロックします。
その他のコマンド
init
.twig/settings.tomlを初期化します。新しいリポジトリでtwigを使い始めるときに実行します。
twig init
# Created .twig/settings.toml
remove
指定したworktreeとbranchを同時に削除します。cleanと同様にsubmoduleの変更を確認して安全に削除します。空になった親ディレクトリも自動でクリーンアップします。
# 単一のworktreeを削除
twig remove feat/old
# 複数のworktreeを削除
twig remove feat/a feat/b feat/c
sync
変更した設定を既存worktreeに適用します。gitignore対象のファイルをsymlinkとして作成し、submoduleの初期化も実行します。
# 特定のworktreeに適用
twig sync feat/a feat/b
# 全worktreeに一括適用
twig sync --all
symlinkのリンク元はdefault_source設定のworktreeです。--sourceで上書きできます。
list
worktree一覧を表示します。
# デフォルト出力(git worktree list互換)
twig list
# パスのみ出力(スクリプトやfzfとの連携に便利)
twig list -q
fzfと組み合わせた例
gcd() {
local selected
selected=$(twig list -q | fzf +m) &&
cd "$selected"
}
補完機能
全てのコマンドでシェル補完が効きます。コンテキストに応じて適切な候補が表示されます。
# removeコマンドでは既存のworktreeが候補に表示される
twig remove <TAB>
# → feat/api feat/auth fix/bug-123
# --sourceオプションではworktreeが存在するブランチのみ候補に表示される
twig add feat/new --source <TAB>
# → main develop feat/api
# --carryオプションでは変更を持ってくる元のworktreeが候補に表示される
twig add feat/new --carry=<TAB>
# → main feat/api feat/auth
# --fileオプションではcarry元worktreeの変更があるファイルが候補に表示される
twig add feat/new --carry --file <TAB>
# → docs/plan.md src/main.go README.md
補完はconfigの設定とflagの指定の両方を考慮します。default_sourceが設定されている場合、その値がデフォルトとして扱われます。--sourceフラグで明示的に指定すると、configの設定を上書きできます。
Claude Code連携
twigはClaude Codeのようなcoding agentとの連携を前提に設計しています。worktree操作の自動化により、agentが複数のタスクを並列で進める際のコンテキスト分離を実現します。
twigの学習不足という問題
Claude Codeはgitのような著名ツールは最適なコマンドを実行します。一方、twigのようなカスタムCLIは学習が不足しています。推測で存在しないコマンドを実行することがあります。
Claude Code pluginによる解決
twigを正しく使うためのpluginを提供しています。
twig-guide
twigのinterfaceを伝えるスキルです。最初にskillをロードするとtwigを賢く使ってくれます。skillの実態は、存在するコマンド一覧と、その詳細仕様へのpathを貼って提供しています。Claude Code skillのドキュメントで紹介されているProgressive Disclosure に則った方法です。
twig-operator
twigによるworktree操作を実行するエージェントです。責務を絞ることで、指示していない操作を勝手に行うことを抑止しています。
plugin インストール
Claude Codeのslash commandで行います。
/plugin marketplace add 708u/twig
/plugin install twig@708u-twig
開発プロセス
ここからは、実際にtwigをClaude Codeを用いて作ってわかったことや、実践した開発プロセスについて紹介します。
Claude Codeで一からCLIを作る体験
元々仕事でClaude Codeを使っていたので、CLAUDE.mdを整備する重要性を実感していました。適切に記述しないとClaude Codeは的外れな動きをします。その経験から、twigでは最初からCLAUDE.mdにプロダクトの適切な情報を記述することを意識していました。主にプロジェクト概要、ディレクトリ構成、アーキテクチャ方針、設計原則、コードスタイル、コミット規約などを最初に固めて記載しています。
また、アプリケーション仕様を表す適切なドキュメントがあれば実装コストが下がることも経験から知っていました。途中からClaude Codeを導入したプロダクトでは、仕様を完全に表すドキュメントを作成することは難しいです。しかし一から作る場合はその限りではありません。そのため、CLIのコマンド仕様を開発と同時に常に同期しています。
以下はtwig clean コマンドの仕様です。これ以外にもすべてのコマンドの仕様を記述しています。
このドキュメントはCLI自体の仕様書であると同時に、Claude Codeがコマンドを理解するためのドキュメントにもなります。ユーザー向けにはREADMEとして提示し、Claude Codeが読み込めるよう.claude/rulesにsymlinkを貼っています。
他にも、coding agentはタスクが長引くほど最初に与えた指示を忘れてしまうという問題があります。CLAUDE.mdや.claude/rulesにいくらcommit前にtestやlintを実行することを指示したとしても、時折忘れたままpushしたりすることがあります。
これを防ぐため、hookを用いてsession内で初回commit前に必ずerrorにして、下記のようにチェックを行ったかを警告出力するようにしています。
Error: PreToolUse:Bash hook error: [python3
.claude/hooks/pre-commit-check/pre-commit-check.py]: BLOCKED: Required checks
not confirmed.
Run before committing:
[code] When Go code (*.go, go.mod, go.sum) is modified
- make test
- make lint
- make fmt
- go mod tidy
[cli] When CLI behavior is modified (cmd/twig/**, *.go)
- Review docs/reference/ for accuracy
- Update docs if command options/behavior changed
[docs] When docs (docs/reference/**) is modified
- make sync-plugin-docs
- Bump version in
external/claude-code/plugins/twig/.claude-plugin/plugin.json
After running checks, commit again to confirm.
1回警告が発生したら、次にcommitするまでは再度警告しないようにしています。
hook自体は claude-official-pluginのsecurity-guidanceを参考にしています。
これの面白いところは、警告は出力するものの、それを実際にアクションするかどうかはClaude Codeに委ねられている点です。最も確実に全てをチェックするのであればhuskyなどでhookしてしまうのが確実ではあるのですが、Claude Codeにチェックを行うべきかどうかを判断させることで、極力不要なtest実行を防ぐことができます。最終的なリードタイムを早くするためのトレードオフとしてちょうどいい落とし所なのではないか、と考えています。
開発を通じて得た学び
Claude Codeで一からCLIを開発する中で、いくつかの気づきがありました。
新規repoとcontext消費
新規repoはcontext消費量が少ないと感じました。普段の仕事ではProgate Path/Prospects をmonorepoで開発しています。CLAUDE.mdや参照コードが大きく、1つのPRで200K tokenを使い切ることが多いです。新規repoは読み出すtokenが少ないため、開発初期は3-4個のPRを同じsessionで作成できました。ただし、repoが大きくなった現在は、1つのPRでcontextを使い切るようになりました。
初期段階で設計を固める
Claude Codeに限った話ではないですが、最初に大枠の設計を固めることが重要だと感じました。今回最初に決めたのは、gitを内部で呼ぶ設計にする、CLI layerとcommand layerを分離する、integration testの方針を決める、などです。これらを最初に決めておき、ドキュメント化とそれに沿ったコードを出力することで、Claude Codeが一貫した実装をしてくれました。
計画の限界と実装によるfeedback
計画して実装しないとわからないな、と思うことが多々ありました。planの精度は概ね80%程度で、残りの20%は実装してみないとわからないと感じました。実装させてみると考慮漏れが見つかったり、実際には実装不可能なものであったりします。不確実性を減らすためには実装してみるしかありません。最終的に実装結果を見てfeedbackし、都度修正していく流れになりました。
アイディアの実現
思いついたことは何でも実現できると感じました。特にtwigを開発している時、twig自身を利用してワークフローをより良くするためのアイディアや、コマンドに追加したい機能が湯水のように湧いてきました。そのアイディアをClaude Codeの/planでメモすると、思考がまとめられて実装可能な案になります。そのままClaude Codeにその計画を渡せば概ね思った通りのものが実装されます。
アウトプットコストの低下
アウトプットコストが激減したと感じています。今までは頭の中で設計して「理論上できそう」で満足していることが多かったです。この 言語化さえできれば自動的にアウトプットが出る という体験は、coding agent全盛の時代において重要なマインドセットなのではと考えています。小さくても形になると加速度的に行動量が増しました。
ワークフローの発展
さて、ここまでtwigについて説明してきました。ここからは発展的な話になります。
twigはClaude Codeを用いて開発しており、worktree管理を便利にして開発効率を上げるためのツールです。そのため、twig add -qが整備されたあたりから、twigの開発にtwigを利用する様になっていました。つまり、twigでworktreeを複数作成し、並列に新機能開発や機能改善をできるようになったということです。
そしてtwigを利用した開発を繰り返すうち、同じ開発サイクルのワークフローを繰り返していることに気づきました。
具体的には以下の手順です。
- plan modeで計画書を作成する
-
twig add feat/xxx -q --carryで新しいworktreeを作成し、計画書を移動する - そのパスをVSCodeで開く
- VSCode内でClaude Codeを起動し、指示書を元に実装を開始する
最初は上記をslash command(現在のSkill)で実装し、作成された新しいworktree上で都度Claude Codeを実行していたのですが、これを繰り返しているうちに「そもそもタスク実行完了まで自動化できるのでは」という可能性に気づきました。
この記事はtwigの説明にとどめますが、後続の記事では上記で思いついた並列実行自動化ワークフローについて解説します。1つの指示から複数のworktreeを自動生成し、それぞれで独立したClaude Codeセッションが実装を完了させる仕組みです。coding agentの可能性をさらに広げる内容になっていると思うので、よろしければぜひお読みください。
まとめ
twigはgit worktreeの操作を抽象化、簡略化するCLIツールであり、その紹介をしました。
worktreeの取り扱いについて同様の課題を感じている方の参考になれば幸いです。
twigを使った開発を通じて、coding agentと組み合わせたときにどのように並列実装を行うと効果的かについても学びが得られました。続編ではこの経験をもとに、並列実行自動化ワークフローについて紹介しています。
Discussion
使ってみました とても良いworktree体験ができております
この記事を読んだところ、現状の他ツールに対しての印象、設計思想、使い方まで共感しかありません
「良さそうだけど、Windows版無いんだろうな・・・」と思っておりましたが、ご対応されており…
開発してくれてありがとうございます
twigを使って頂きありがとうございます!
ツールの解説が終わったなというタイミングで始まった「開発プロセス」が面白くてむしろこちらが本編かと感じました。
「twigの学習不足という問題」については同じくcode agentが叩くことを想定して作られたagent-browerでは
AGENTS.md / CLAUDE.mdに使い方概要とヘルプへの動線を書いてもらうことで問題を軽減しているようです。--helpの出力内容も参考になるんじゃないかと思います。
ありがとうございます!agent-browser知らなかったです、勉強になります!
今回の記事では省略していたんですが、仰る通りどのようにClaude Codeにtwigを賢く使ってもらうかについて、色々やり方がありそうだなと思っています。
--helpをclaude codeに叩かせるのは、実は最初に思いついた方法でした。documentを書かずに済むので実装コストがほぼゼロのためです。ただ、これを試してみたところ、
--helpにコマンド仕様詳細が載っておらず、Claude Codeがhelp内容から実際に発生する処理を推察してしまうという問題があり、断念しました。--helpの説明を厚くするという方向性もありえたのですが、CLIツールとして利用したときに過度に説明的な文章が表示されるので、エンジニアがcliのargsやoptionを知りたい時に不便かなと考えて辞めました。記事内でも触れていますが、できる限りエンジニアもcoding agentも使いやすいことを目指していたので、過度に生成AIに寄り添った要素を入れるのを避けたかったためです。また、実装仕様やspecをhostingして都度見に行かせるというのも実は案としてはありました。まさしくご提示頂いているagent-browserのやり方に近いです。claude code標準の claude-code-guide agentも似たような仕組みを取っており、それを参考にするイメージでした(claude codeに仕様のindexとpromptが書かれたページにアクセスさせて、必要な情報のみを取得する)。
ただ、今のtwigのspecに対して、わざわざdocsのhosting先を用意する規模に至っているのだろうか?という懸念と、cli自体の仕様が大きくなく、膨大な仕様の中から必要なものだけとってくる、という処理も現時点では大振りかな、という判断から一旦候補から外しました。(将来的には対応するかもしれません)
もう一点、SKILLとして提供するのであれば今のところ動的に外部から知識をfetchしてくるより、mdに直接記述して渡してしまったほうが、標準の仕組みでloadできるのでより高速に動作してくれるのでは?という仮説があります。SKILLがclaudeのchatでloadできるポータビリティを一応担保するという観点もあります。
上記を踏まえ、今のところは仕様書を直接渡してしまう方法がよさそうなのかな、と判断して記事内で紹介した方法になっています。