Files
claude-video/dev-sync.sh
T
bradautomates 429f3143e5 Restructure as a self-contained Agent Skills package (fix Codex install)
Move the skill into skills/watch/ so SKILL.md and its scripts/ runtime are
siblings inside one folder. `npx skills add` (Codex/Cursor/Copilot/agents) now
copies a working skill as a unit; previously it grabbed the root SKILL.md alone
and left scripts/ behind, so the skill was dead on arrival on every non-Claude
host. Mirrors the layout last30days-skill adopted for the same reason.

- skills/watch/{SKILL.md,scripts/}: self-contained skill folder
- SKILL.md: resolve a harness-agnostic $SKILL_DIR (the dir it was Read from)
  instead of the Claude-Code-only ${CLAUDE_SKILL_DIR}; guard + 19 call sites
- drop commands/watch.md: /watch derives from frontmatter (name + user-invocable)
- .codex-plugin/plugin.json: full manifest with "skills": "./skills/" + interface
- add .agents/plugins/marketplace.json, AGENTS.md, CLAUDE.md, .skillignore
- build-skill.sh: archive the skills/watch subtree (one SKILL.md, no zip -d)
- fix paths in tests, hooks hint, .gitattributes, release.yml
- relocate dev-sync.sh to repo root and fix REPO_ROOT
- README: content-ideas structure, npx skills install, star history

Verified: 37/37 tests pass; npx skills add bundles the full scripts/ runtime;
manifests valid; versions synced at 0.1.3.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 22:12:54 +10:00

88 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# dev-sync.sh — copy this working tree into the installed /watch plugin cache so
# local edits are picked up by Claude Code without publishing a release.
#
# The install path is resolved from ~/.claude/plugins/installed_plugins.json, so
# it follows version bumps automatically. Override it by passing a path as $1 or
# setting WATCH_INSTALL_PATH. Pass --dry-run to preview without writing.
#
# Usage:
# ./dev-sync.sh # sync into the resolved install path
# ./dev-sync.sh --dry-run # show what would change
# ./dev-sync.sh /some/other/dir # sync into an explicit path
#
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_KEY="watch@claude-video"
INSTALLED_JSON="${HOME}/.claude/plugins/installed_plugins.json"
DRY_RUN=()
DEST=""
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=(--dry-run --itemize-changes) ;;
-*) echo "unknown flag: $arg" >&2; exit 2 ;;
*) DEST="$arg" ;;
esac
done
# Resolve the destination install path if not given explicitly.
if [[ -z "$DEST" ]]; then
DEST="${WATCH_INSTALL_PATH:-}"
fi
if [[ -z "$DEST" ]]; then
if [[ ! -f "$INSTALLED_JSON" ]]; then
echo "error: $INSTALLED_JSON not found; pass an install path explicitly" >&2
exit 1
fi
DEST="$(PLUGIN_KEY="$PLUGIN_KEY" python3 - "$INSTALLED_JSON" <<'PY'
import json, os, sys
data = json.load(open(sys.argv[1]))
key = os.environ["PLUGIN_KEY"]
records = data.get("plugins", {}).get(key, [])
# Prefer a record whose installPath actually exists on disk.
paths = [r.get("installPath") for r in records if r.get("installPath")]
for p in paths:
if os.path.isdir(p):
print(p); break
else:
print(paths[0] if paths else "")
PY
)"
fi
if [[ -z "$DEST" ]]; then
echo "error: could not resolve an install path for '$PLUGIN_KEY'" >&2
echo " install the plugin first, or pass a path: scripts/dev-sync.sh /path/to/install" >&2
exit 1
fi
if [[ ! -d "$DEST" ]]; then
echo "error: install path does not exist: $DEST" >&2
exit 1
fi
echo "source: $REPO_ROOT"
echo "dest: $DEST"
echo
# Mirror shipped files only. Dev-only artifacts and runtime state are excluded.
# No --delete: the cache holds runtime state (.in_use/) we must not touch.
rsync -a ${DRY_RUN[@]+"${DRY_RUN[@]}"} \
--exclude '.git/' \
--exclude '.venv/' \
--exclude '.pytest_cache/' \
--exclude '__pycache__/' \
--exclude '*.pyc' \
--exclude '.DS_Store' \
--exclude '.in_use/' \
--exclude 'tests/' \
--exclude 'docs/' \
--exclude 'dist/' \
--exclude 'V2_*.md' \
--exclude 'dev-sync.sh' \
"$REPO_ROOT/" "$DEST/"
echo "done."