56 lines
2.2 KiB
Bash
Executable File

#!/usr/bin/env bash
# Installs the locally built plugin into the host's plugin directory, so the
# host picks up `npm run build` output without a reinstall from its URL.
#
# It copies rather than symlinks, and that is not a matter of taste:
# `scanPlugins()` walks the plugins directory with
# `readdirSync(dir, { withFileTypes: true })` and skips every entry whose
# `entry.isDirectory()` is false — which is exactly what a symlink reports. A
# symlinked plugin is silently invisible to the host.
# Symlinking the files *inside* a real directory fails too: the asset route
# compares the `realpath` of each asset against the `realpath` of the plugin
# directory and 404s anything pointing outside it.
#
# Usage: ./scripts/link-plugin.sh [--remove]
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DIR_NAME="cloudcli-plugin-taskwork" # last URL segment — how the host names it
TARGET="${HOME}/.claude-code-ui/plugins/${DIR_NAME}"
SOURCE="$ROOT/plugin-taskwork"
# Everything the host needs at runtime: manifest, entry points, icon, and the
# package.json it reads to decide whether to run a build.
CONTENTS=(manifest.json package.json icon.svg build)
if [ "${1:-}" = "--remove" ]; then
[ -e "$TARGET" ] && rm -rf "$TARGET" && echo "removed $TARGET" || echo "nothing to remove"
exit 0
fi
[ -f "$SOURCE/manifest.json" ] || { echo "plugin-taskwork/manifest.json not found — run ./scripts/bootstrap.sh" >&2; exit 1; }
[ -d "$SOURCE/build" ] || { echo "plugin-taskwork/build missing — run npm run build in plugin-taskwork/" >&2; exit 1; }
if [ -L "$TARGET" ]; then
echo "removing a stale symlink at $TARGET (the host cannot see symlinked plugins)"
rm "$TARGET"
fi
mkdir -p "$TARGET"
rm -rf "${TARGET:?}/build"
for item in "${CONTENTS[@]}"; do
cp -r "$SOURCE/$item" "$TARGET/"
done
# Intermediate tsc output is a build artefact, not part of the plugin.
rm -rf "$TARGET/build/.tsc-client"
echo "installed $TARGET (copy of $SOURCE)"
cat <<'EOF'
Re-run this script after every `npm run build`; a copy does not track the source.
Client changes need the plugin surface reopened, server changes need the host
restarted — the plugin's backend process is spawned once at host startup.
EOF