Skip to content

Instantly share code, notes, and snippets.

@koki-h
Created March 10, 2026 01:41
Show Gist options
  • Select an option

  • Save koki-h/bfbce63f7a3ec20b70978d0f9b4056d5 to your computer and use it in GitHub Desktop.

Select an option

Save koki-h/bfbce63f7a3ec20b70978d0f9b4056d5 to your computer and use it in GitHub Desktop.
opencodeサーバ起動とChromeでVISを開くのをまとめて行うスクリプト
#!/bin/bash
# macOS 用。opencode serve を起動し、Chrome の Local Network Access ポリシーを設定したうえで
# https://xenodrive.github.io/vis/ を app 風ウィンドウで開きます。
# ウィンドウを閉じたらローカルサーバも自動停止します。
set -euo pipefail
# =========================
# 設定
# =========================
OPENCODE_PORT="${OPENCODE_PORT:-4096}"
OPENCODE_HOST="${OPENCODE_HOST:-127.0.0.1}"
OPENCODE_ORIGIN="${OPENCODE_ORIGIN:-https://xenodrive.github.io}"
VIS_URL="${VIS_URL:-https://xenodrive.github.io/vis/}"
CHROME_APP_NAME="${CHROME_APP_NAME:-Google Chrome}"
RUNTIME_DIR="$HOME/.opencode-vis-launcher"
PID_FILE="$RUNTIME_DIR/opencode.pid"
LOG_FILE="$RUNTIME_DIR/opencode.log"
USER_DATA_DIR="$HOME/Library/Application Support/OpenCodeVisApp"
# Chrome policy
CHROME_POLICY_DOMAIN="${CHROME_POLICY_DOMAIN:-com.google.Chrome}"
CHROME_POLICY_PLIST="${CHROME_POLICY_PLIST:-/Library/Managed Preferences/${CHROME_POLICY_DOMAIN}.plist}"
CHROME_POLICY_ALLOWED_URL="${CHROME_POLICY_ALLOWED_URL:-https://xenodrive.github.io}"
WRITE_CHROME_POLICY="${WRITE_CHROME_POLICY:-1}"
mkdir -p "$RUNTIME_DIR"
mkdir -p "$USER_DATA_DIR"
# Automator / Finder 起動では PATH が極端に短いことが多いので補強する
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$HOME/.local/bin:$HOME/bin:$HOME/.npm-global/bin:$HOME/node_modules/.bin:$HOME/.bun/bin:$PATH"
is_server_alive() {
curl -fsS "http://${OPENCODE_HOST}:${OPENCODE_PORT}/app" >/dev/null 2>&1 || \
curl -fsS "http://${OPENCODE_HOST}:${OPENCODE_PORT}/" >/dev/null 2>&1
}
cleanup_stale_pid() {
if [[ -f "$PID_FILE" ]]; then
local old_pid
old_pid="$(cat "$PID_FILE" 2>/dev/null || true)"
if [[ -n "$old_pid" ]] && ! kill -0 "$old_pid" 2>/dev/null; then
rm -f "$PID_FILE"
fi
fi
}
find_opencode() {
# 1) 今の PATH
if command -v opencode >/dev/null 2>&1; then
command -v opencode
return 0
fi
# 2) zsh のログインシェル環境を読む(mac の通常利用に近い)
local from_zsh=""
from_zsh="$(zsh -lic 'command -v opencode 2>/dev/null || true' 2>/dev/null | tail -n 1)"
if [[ -n "$from_zsh" && -x "$from_zsh" ]]; then
echo "$from_zsh"
return 0
fi
# 3) よくある配置場所を総当たり
local candidates=(
"/opt/homebrew/bin/opencode"
"/usr/local/bin/opencode"
"$HOME/.local/bin/opencode"
"$HOME/bin/opencode"
"$HOME/.npm-global/bin/opencode"
"$HOME/.bun/bin/opencode"
)
local p
for p in "${candidates[@]}"; do
if [[ -x "$p" ]]; then
echo "$p"
return 0
fi
done
return 1
}
ensure_chrome_policy() {
[[ "$WRITE_CHROME_POLICY" == "1" ]] || return 0
echo "Chrome ポリシーを確認します: $CHROME_POLICY_PLIST"
echo "許可 URL: $CHROME_POLICY_ALLOWED_URL"
# 既に許可済みなら何もしない
if sudo defaults read "$CHROME_POLICY_PLIST" LocalNetworkAccessAllowedForUrls 2>/dev/null | grep -Fq "$CHROME_POLICY_ALLOWED_URL"; then
echo "Chrome ポリシーは既に設定済みです。"
return 0
fi
echo "Chrome ポリシーを書き込みます(管理者権限が必要です)..."
sudo mkdir -p "/Library/Managed Preferences"
# 配列を作り直して、必要 URL を入れる
sudo /usr/libexec/PlistBuddy -c "Delete :LocalNetworkAccessAllowedForUrls" "$CHROME_POLICY_PLIST" 2>/dev/null || true
sudo /usr/libexec/PlistBuddy -c "Add :LocalNetworkAccessAllowedForUrls array" "$CHROME_POLICY_PLIST"
sudo /usr/libexec/PlistBuddy -c "Add :LocalNetworkAccessAllowedForUrls:0 string $CHROME_POLICY_ALLOWED_URL" "$CHROME_POLICY_PLIST"
echo "Chrome ポリシーを書き込みました。"
echo "既に Chrome が起動中なら、完全終了後に再起動したほうが確実です。"
}
stop_server() {
if [[ -f "$PID_FILE" ]]; then
local pid
pid="$(cat "$PID_FILE" 2>/dev/null || true)"
if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then
echo "opencode server を停止します (PID: $pid)"
kill "$pid" 2>/dev/null || true
for _ in {1..10}; do
if ! kill -0 "$pid" 2>/dev/null; then
break
fi
sleep 1
done
if kill -0 "$pid" 2>/dev/null; then
kill -9 "$pid" 2>/dev/null || true
fi
fi
rm -f "$PID_FILE"
fi
}
start_server() {
cleanup_stale_pid
if is_server_alive; then
echo "opencode server は既に起動しています: http://${OPENCODE_HOST}:${OPENCODE_PORT}"
return 0
fi
local opencode_bin=""
if ! opencode_bin="$(find_opencode)"; then
cat >&2 <<MSG
エラー: opencode コマンドが見つかりません。
対処候補:
1. ターミナルで 'which opencode' を実行して場所を確認する
2. このスクリプト先頭で OPENCODE_BIN にその絶対パスを指定する
例: OPENCODE_BIN=/opt/homebrew/bin/opencode
現在の PATH:
$PATH
MSG
exit 1
fi
echo "使用する opencode: $opencode_bin"
echo "opencode serve を起動します..."
nohup "$opencode_bin" serve --cors "$OPENCODE_ORIGIN" --hostname "$OPENCODE_HOST" --port "$OPENCODE_PORT" \
>"$LOG_FILE" 2>&1 &
local pid=$!
echo "$pid" > "$PID_FILE"
for _ in {1..60}; do
if is_server_alive; then
echo "opencode server 起動完了: http://${OPENCODE_HOST}:${OPENCODE_PORT}"
return 0
fi
sleep 1
done
echo "エラー: opencode server の起動確認に失敗しました。ログ: $LOG_FILE" >&2
exit 1
}
open_vis_app() {
local chrome_path="/Applications/${CHROME_APP_NAME}.app"
if [[ ! -d "$chrome_path" ]]; then
echo "エラー: /Applications/${CHROME_APP_NAME}.app が見つかりません。" >&2
echo "CHROME_APP_NAME を 'Google Chrome' / 'Google Chrome Canary' / 'Microsoft Edge' などに変更してください。" >&2
exit 1
fi
echo "Visualizer を単体アプリ風ウィンドウで開きます..."
open -na "$CHROME_APP_NAME" --args \
--app="$VIS_URL" \
--user-data-dir="$USER_DATA_DIR" \
--disable-background-mode \
--window-size=1440,980
}
wait_for_vis_close() {
local found_once=0
echo "VIS ウィンドウが閉じられるのを監視します..."
while true; do
if pgrep -af "$USER_DATA_DIR" >/dev/null 2>&1; then
found_once=1
else
if [[ "$found_once" -eq 1 ]]; then
echo "VIS 用 Chrome が終了しました。"
return 0
fi
fi
sleep 2
done
}
trap 'stop_server' EXIT INT TERM
ensure_chrome_policy
start_server
open_vis_app
wait_for_vis_close
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment