Binky について
BinkyはGit worktreeごとに独立したローカル環境を作り、ポート、環境変数、サービスプロセス、共有データベースなどのリソーススライスを管理します。1台のマシンでコーディングエージェントやブランチを並行して動かすチーム向けです。
主な機能
- 01worktreeごとのポート・URL・環境分離
- 02サービス別リソーススライスの用意
- 03worktreeサービスの起動・停止・確認
- 04アドミッション制御とバックグラウンド監視
- 05コマンドラインとライブダッシュボード
活用シーン
- 01コーディングエージェントをポート競合なく並行実行
- 02ブランチごとに独立したデータベーススライスを用意
- 03テストやエージェントにworktreeのURLと環境を渡す
MCP 対応
`binky mcp`はstdioでMCPサーバーを実行し、CLIと同じデーモンを使う`up`、`down`、`status`、`env`、`verify`ツールを公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
5掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| root | string | いいえ | |
| group | string | いいえ | |
| worktree | string | はい |
詳細
Binky
git worktree ごとに独立したローカル環境を用意します。ポート、環境変数、データベース、URL を分離します。
1 台のマシンでコーディングエージェントを並列実行しても、互いに干渉しません。
ドキュメント · クイックスタート · アダプター · コマンド · エージェント向け · 仕組み · トラブルシューティング
docker-compose は一度に 1 つのプロセスを実行するために作られました。Binky は一度に 15 個のプロセスを実行するために作られています。
ステータス:アルファ版。 worktree の分離、ポート、アダプター、監視、調整、受け入れ制御、プロキシ、HTTPS といった中核機能は、最初から最後まで動作します。設定形式は安定していますが、CLI は今後変更される可能性があります。
問題
同じリポジトリで 3 つのエージェントを動かしているとします。2 つ目が pnpm dev を実行すると EADDRINUSE が発生します。3 つ目がマイグレーションを実行し、1 つ目が読み取り中のテーブルを削除してしまいます。.env ファイルを手作業で編集し始め、気づけば自分がスケジューラーになっています。
Binky がそのスケジューラーになります。エージェントごとに binky up <branch> を実行するだけで、それぞれに専用のポート、データベース、URL が割り当てられます。すべて同じコミット済みの設定から作成されます。
インストール
Binky が実際にテストされている Linux と Windows のどちらかで、Python 3.11 以降と git が必要です。macOS はまだサポート対象ではありません。十分にテストされた移植への貢献を歓迎します。
uv tool install binky # or: pipx install binky
binky --version
未リリースの main を実行したい場合や、開発に取り組む場合は、クローンからインストールすることもできます。
git clone https://github.com/andreisilva1/binky && cd binky
uv tool install . # or: pipx install .
ドライバーが必要なアダプターは、追加機能として提供されます。Redis 用に Binky をインストールしても、boto3 はインストールされません。
uv tool install "binky[postgres]" # or [redis], [mysql], [mongodb], [s3], [kafka]
uv tool install "binky[all-adapters]" # the whole matrix
クイックスタート
すでに docker-compose.yml がある場合は、そこから始められます。
binky init # writes a binky.toml you can read and edit
binky check # validate it
または、手作業で記述することもできます。設定全体は次のとおりです。
[project]
name = "acme"
[services.web]
cmd = "pnpm dev --port ${self.port}"
url = "web" # → web.<worktree>.acme.localhost
depends_on = ["api"]
env = { API_URL = "${api.url}" }
[services.api]
cmd = "go run ./cmd/server"
url = "api" # asking for a URL is what asks for a port
depends_on = ["db"]
env = { DATABASE_URL = "${db.url}" }
[services.db]
adapter = "postgres" # a private database per worktree
admin_url = "${env.POSTGRES_ADMIN_URL}"
migrate = "make migrate"
seed = "make seed"
clone_from = "golden" # migrate+seed once, then copy per worktree
続いて、worktree を並列で起動します。
$ binky up login-fix
api pid 16560 :4846
web pid 29732 :4504
✓ up: login-fix (2 service(s))
$ binky up checkout-v2
api pid 21768 :4137
web pid 46336 :4605
✓ up: checkout-v2 (2 service(s))
$ binky status
acme
checkout-v2 [running]
api :4137
web :4605
login-fix [running]
api :4846
web :4504
ブランチ 2 つ、プロセス 4 つ、手作業で選ぶ必要のないポート 4 つです。worktree の接続情報を、必要とする相手(シェル、エージェント、テスト実行など)に渡します。
$ binky env login-fix --dotenv
WEB_URL=http://web.login-fix.acme.localhost
API_URL=http://api.login-fix.acme.localhost
残りのライフサイクル操作は次のとおりです。
binky down login-fix # pause (keeps files + ports); `up` again is instant
binky remove login-fix # destroy it (refuses if there are uncommitted changes)
ハードコードされた値はなく、実行時に検出されるものもありません。すべてのプロセスは、自身と依存先のポートマップ全体を把握した状態で起動します。
覚えておくべきルールが 1 つあります。 サービスに
urlまたはportsを宣言すると、ポートが割り当てられます。ポートの要求は明示的に行います。どちらも宣言されていないサービスにはポートが割り当てられません。ワーカーや単発ジョブにはこれが正しい動作ですが、そのサービスのcmdに${self.port}を書くと問題になります。不明なトークンは空文字列に置き換えず、そのまま残すため、文字列${self.port}がシェルに渡り、プロセスは自身の引数解析時にエラー終了します。このような記述があると、binky checkが警告します。
N 個のワールドを実行するコスト
N 個の隔離されたワールドを実行しても、コストが 1 個のワールドの N 倍になる必要はありません。これは主張ではなく、測定結果です。benchmarks/worlds.py はこのリポジトリにあり、以下の表を再現できます(postgres:16、各ワールド 200,000 行、Windows 11 上の Docker Desktop)。
| worlds | RAM: a container each | RAM: Binky | time: a container each | time: Binky |
|---|---|---|---|---|
| 1 | 150 MiB | 174 MiB | 6s | 4s |
| 2 | 298 MiB | 182 MiB | 11s | 6s |
| 4 | 596 MiB | 228 MiB | 20s | 10s |
| 8 | 1197 MiB | 295 MiB | 40s | 16s |
8 個目のワールドは、それぞれを独立したコンテナーにすると +150 MiB、+4.8s かかりますが、Binky では +17 MiB、+1.7s です。
最初の行も確認してください。ワールドが 1 つの場合、Binky は劣ります。サーバーと、まだ使うものがないゴールデンテンプレートの分のコストがかかり、それを回収できるのは 2 つ目以降です。また、ディスク容量の面で有利になるわけではありません。CREATE DATABASE ... TEMPLATE はコピーオンライトではなくファイルのコピーなので、各ワールドには引き続き行データの完全なコピーが必要です。Binky が取り除くのはワールドごとの サーバー であり、ワールドごとの バイト数 ではありません。また、アプリのプロセス自体のコストも下がりません。ワークツリーごとに開発サーバーを 1 つ実行する場合、どちらの方法でもコストは同じです。
python benchmarks/worlds.py --sweep 1,2,4,8 --rows 200000
Binky が不要な場合
表の最初の行にもあるとおり、これははっきり述べておく価値があります。
- 一度に 1 つのブランチしか使わない場合。 2 つのワールドを同時に起動することがないなら、Binky は不要なデーモンと設定ファイルを増やすだけです。2 つ目のエージェントが登場したら使いましょう。
- すべてがすでにコンテナーで動いていて、それで問題ない場合。 Binky の利点は、ワールドごとの サーバー をなくせることです。Docker Compose のスタックが十分に小さく、N 個のコピーを無理なく動かせるなら、取り戻せるものはありません。
- ローカルでの隔離ではなく、実際の隔離が必要な場合。 Binky はお使いのマシン上で、あなたと同じユーザーとしてコマンドを実行します。サンドボックスではありません。詳しくはセキュリティをご覧ください。
アダプター
アダプターは、ワークツリーごとに 1 つのサーバーを実行する代わりに、共有サーバー 1 つの独立したスライス(データベース、キーのプレフィックス、バケットなど)を切り分けます。16 個の名前、10 個の実装すべてについて、CI で実サーバーを使ったテストを実施しています。
| slice | adapters |
|---|---|
| データベース | postgres · mysql · mariadb · percona · mongodb · clickhouse |
| キーのプレフィックス | redis · valkey |
| バケット/プレフィックス | s3 · minio |
| vhost/トピックのプレフィックス | rabbitmq · kafka · redpanda |
| コレクション | qdrant |
| インデックスのプレフィックス | elasticsearch · opensearch |
プロトコル互換の名前は、それぞれ別の実装を複製するのではなく、共通の実装を使用します。valkey は Redis アダプター、percona は MySQL アダプター、opensearch は Elasticsearch アダプターです。
clone_from:migrate+seed のコストを 1 回にする
clone_from を使用すると、最初の binky up でゴールデンテンプレートが作成されます。プロビジョニング、マイグレーション、シードを行い、それ以降の各ワークツリーはそのテンプレートをコピーします。テンプレートは migrate と seed の各コマンドのハッシュで識別されるため、どちらかを変更すると自動的に再構築されます。
サーバー側でスライスをコピーできる場合(postgres、mysql、mariadb、percona、mongodb)に対応しています。対応していない場合や、環境上の理由(認証に必要なクライアントバイナリが古い、必要な権限がないなど)でクローンに失敗した場合、Binky はそのワークツリーについてプロビジョニング、マイグレーション、シードにフォールバックし、clone_fallback をログに記録します。正しさはクローンに依存しません。クローンが左右するのは速度だけです。
注意すべき点が 1 つあります。ハッシュに含まれるのは migrate と seed の コマンド であり、それらが呼び出すファイルではありません。コマンドから実行されるスクリプトを編集しても、テンプレートは再構築されません。再構築を強制するには、~/.binky/golden/ 内のマーカーを削除してください。
独自のアダプターを作成する
2つの方式があり、契約は共通です。どちらも同じ4つの操作を実装します。
| 操作 | 内容 |
|---|---|
provision(slice) | スライスを作成します(CREATE DATABASE ...) |
resolve(slice) | アドレスを返します → ${db.url} |
teardown(slice) | スライスを破棄します |
capabilities() | 対応機能を返します。例:{"clone": true} |
プロセス内アダプターは、このリポジトリ内のPythonクラスで、名前で検出されます。外部アダプターは、任意の言語で作成した実行ファイルで、PATH 上の binky-adapter-<name> として検出され、1回限りのサブプロセスとJSONプロトコルで動作します。
$ binky-adapter-filestore provision <<< '{"slice": "acme_login-fix", "config": {}}'
{"ok": true}
$ binky-adapter-filestore resolve <<< '{"slice": "acme_login-fix", "config": {}}'
{"ok": true, "address": "file:///tmp/binky-filestore/acme_login-fix"}
Pythonで作成する場合、プロトコルは自動的に利用できます。binky.adapter_sdk.run() が通常のアダプタークラスとプロトコルの橋渡しをします。依存関係なしで30行で実装した完全な例は、examples/adapters/filestore.py を参照してください。
コマンド
| コマンド | 内容 |
|---|---|
binky init [dir] [--force] | docker-compose.yml と .env から初期設定用の binky.toml を作成します |
binky check [path] | binky.toml を検証し、危険な設定を警告します |
binky up <name> [--group g] | ブランチのワークツリーを作成/使用し、ポートを割り当て、リソースをプロビジョニングして、サービスを起動します |
binky reload <name> [--group g] | その場で再起動します。停止後、同じポートとデータで起動し直します |
binky down <name> | ワークツリーのプロセスを停止します(ファイルとポートは保持します) |
binky remove <name> [--force] | ワークツリーを破棄します。停止し、スライスを削除して、ファイルを取り除きます |
binky status [.] | ワークツリーを一覧表示します(プロジェクト別にグループ化)。. は現在のプロジェクトのみを示します |
binky env <name> [--dotenv] | ワークツリーの公開された接続情報を、自分またはエージェント向けに出力します |
binky curl <name> <service> [path] | Host ヘッダーを設定して、プロキシ経由でサービスを呼び出します(-X/-d/-H/-i/-f) |
binky verify <name> | プロジェクトの agents.verify チェックを実行します。失敗するとゼロ以外の終了コードを返します |
binky logs <name> | ワークツリーで取得したサービスログを出力します |
binky gc | クラッシュによってプロビジョニングが途中で止まった、孤立したアダプタースライスを一掃します |
binky config | マシン全体に適用される設定(RAM/ディスクの予約量、プロキシポート)を表示します |
binky reserve [--ram %] [--disk gb] | Binkyが常に空けておくRAM/ディスク容量を設定します |
binky port [--proxy p] [--https p] | プロキシ/HTTPSポートを設定します |
binky dashboard | すべてのワークツリーをリアルタイムで表示するTUI |
binky doctor | インストールとデーモンを診断します。問題がある場合はゼロ以外の終了コードを返します |
binky metrics | デーモンの特定時点のメトリクスをJSON形式で出力します |
binky mcp | エージェントがBinkyの操作をツールとして呼び出せるよう、MCP サーバーを実行します |
binky daemon start|stop|status | バックグラウンドデーモンを管理します |
エージェント向け
binky mcp はstdio経由でMCPを使用し、up、down、status、env、verify を公開します。これらはCLIが呼び出すものと同じ操作で、同じデーモンを使用します。
Claude Codeでは、1行で接続できます。
claude mcp add binky -- binky mcp
プロトコルに対応する他のクライアントでも、同じstdioサーバーを設定ブロックとして指定します。どこでも同じ設定を使い、異なるのはファイルだけです。
{ "mcpServers": { "binky": { "command": "binky", "args": ["mcp"] } } }
何もインストールせずに実行するには、代わりに uvx を使います。claude mcp add binky -- uvx --from "binky[mcp]" binky mcp と実行するか、設定ブロックとして "command": "uvx"、"args": ["--from", "binky[mcp]", "binky", "mcp"] を指定します。ワークツリーでアダプタースライスをプロビジョニングするプロジェクトでは、該当する追加機能も指定します。例:binky[mcp,postgres](すべてのアダプターを含める場合は binky[mcp,all-adapters])。
BinkyはMCP Registryに io.github.andreisilva1/binky として公開されているため、レジストリに対応するクライアントから検索してインストールできます。
ツール一覧とエージェント向けの手順については、AGENTS.md を参照してください。
仕組み
マシン全体で動作する単一のデーモンが、ワークツリーとマシンの間に配置されます。
flowchart TB
CLI["agents · CLI · MCP"] -->|"up · down · status"| D(("binky daemon<br/>machine-global"))
D --> ADM{"admission<br/>RAM · disk · max_parallel"}
ADM -.->|"no room → queue / suspend"| Q["waiting"]
ADM -->|"admit"| W["worktree<br/>git worktree per name"]
W --> P["ports<br/>whole map before start"]
P --> R["adapters<br/>isolated slice per worktree"]
R --> S["supervisor<br/>depends_on · health · logs"]
S --> X["proxy<br/>svc.worktree.domain → port"]
D -.->|"reads · writes"| ST[("~/.binky<br/>SQLite + settings")]
- ワークツリー — 名前ごとに Git ワークツリーを作成または使用します。
- ポート — グローバルアロケーターが、プロセスの起動前にすべてのプロセスへポートを割り当て、ポートのマップ全体を注入するため、競合は発生しません(
${self.port}、${api.url}など)。 - リソース — アダプターがワークツリーごとに分離された領域を切り出し、削除時に後片付けをします。
- 監視 —
depends_onの順にサービスを起動し、ヘルスチェックを待ち、ログを取得します。 - プロキシ —
<service>.<worktree>.<domain>を適切なポートにルーティングします(WebSocket/HMR にも対応)。https = trueを設定すると、Caddy が PATH 上にある場合、Binky はローカル CA を介した TLS のために Caddy の前段に配置されます。 - 起動制御 — マシンに余裕がある場合にのみワークツリーを起動する FIFO キューです。実行中のワークツリーが
max_parallel未満で、かつ十分な空き RAM(一定割合を予備として確保)と十分な空きディスク容量(固定 GB の余裕)がある場合に起動します。実行中のワークツリー群が後から RAM の予備量を下回ると、デーモンは負荷を軽減するため、最も新しいワークツリーを一時停止し、余裕が戻ったら公平性に基づく順序で再開します。binky reserveで予備量を調整し、binky configで確認できます。
状態は ~/.binky/ に保存されます(SQLite レジストリと設定ストアがあり、アップグレード時にその場で移行されます)。クラウド上では何も実行されず、Binky がホームに情報を送信することもありません。
例
- examples/hello — 最小構成のプロジェクトです。
- examples/rag — 各ワークツリーが独自の埋め込みコーパスを持つベクトル検索です。
データベースを共有すると実際に問題が起きるケースです。2 つのエージェントが再インデックスを行い、一方が
TRUNCATEします。 - examples/adapters/filestore.py — 完全な外部アダプターです。
セキュリティ
Binky は、あなたのマシン上で、あなたとして、あなたのコマンドを実行します。これは単一ユーザーのワークステーション向けの開発ツールであり、マルチテナントのサンドボックスではありません。binky.toml は Makefile と同じくらい信頼できるものであり、信頼できないリポジトリで binky up を実行するのは、信頼できないリポジトリで make を実行するのと同じです。脅威モデルと、明示的に対象外としている内容は SECURITY.md に記載されています。
ここで改めて強調しておきたいルールは 1 つです。コミットする binky.toml に認証情報を直接記述しないでください。${env.NAME} または env_file を使用してください。binky check はそのような記述があると警告し、binky init が認証情報を書き込むことはありません。
動作しない場合
TROUBLESHOOTING.md では、実際によく起きるケースを説明しています。外部で使用中のポート、$PORT を無視する開発サーバー、古いゴールデンテンプレート、名前解決できない *.localhost などです。まずは binky doctor を実行してください。
開発
python -m venv .venv && . .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e ".[dev,all-adapters]"
pytest
ruff check src tests examples benchmarks
実サーバーを指定しない限り、アダプターの統合テストはスキップされます。対象となる環境変数は BINKY_TEST_PG、BINKY_TEST_REDIS、BINKY_TEST_MYSQL、BINKY_TEST_MONGO、BINKY_TEST_S3、BINKY_TEST_RABBITMQ、BINKY_TEST_KAFKA、BINKY_TEST_QDRANT、BINKY_TEST_CLICKHOUSE、BINKY_TEST_ELASTICSEARCH です。CI ではこれらすべてが用意されています。
貢献
バグ報告、新しいアダプター、PR を歓迎します。環境のセットアップ方法は CONTRIBUTING.md を、内部構造の概要は ARCHITECTURE.md をご覧ください。
ライセンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。