CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
build-dxt.sh
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| cd4f63b | 1 | #!/usr/bin/env bash |
| 2 | # ============================================================================= | |
| 3 | # BLOCK Q1 — Claude Desktop (.dxt) extension build script. | |
| 4 | # | |
| 5 | # bash scripts/build-dxt.sh | |
| 6 | # | |
| 7 | # What it does: | |
| 8 | # 1. Validates extension/gluecron.dxt/manifest.json is parseable JSON | |
| 9 | # 2. Regenerates placeholder icon.png + screenshot-1.png (idempotent) | |
| 10 | # 3. Zips everything under extension/gluecron.dxt/ into public/gluecron.dxt | |
| 11 | # 4. Prints the size + path | |
| 12 | # | |
| 13 | # Output: | |
| 14 | # public/gluecron.dxt — the user-facing extension bundle, served by | |
| 15 | # GET /gluecron.dxt (see src/routes/dxt.ts). | |
| 16 | # | |
| 17 | # Re-runnable. Safe to call on every deploy. No third-party deps beyond | |
| 18 | # system `zip` (available on macOS, Linux, WSL). | |
| 19 | # ============================================================================= | |
| 20 | ||
| 21 | set -euo pipefail | |
| 22 | ||
| 23 | ROOT="$(cd "$(dirname "$0")/.." && pwd)" | |
| 24 | SRC_DIR="$ROOT/extension/gluecron.dxt" | |
| 25 | OUT_DIR="$ROOT/public" | |
| 26 | OUT_FILE="$OUT_DIR/gluecron.dxt" | |
| 27 | ||
| 28 | # ── pretty printers ───────────────────────────────────────────────────────── | |
| 29 | say() { printf "\n\033[1;34m> %s\033[0m\n" "$*"; } | |
| 30 | ok() { printf " \033[32mv\033[0m %s\n" "$*"; } | |
| 31 | warn() { printf " \033[33m!\033[0m %s\n" "$*"; } | |
| 32 | fail() { printf " \033[31mx\033[0m %s\n" "$*"; exit 1; } | |
| 33 | ||
| 34 | # ── 1. Prerequisites ──────────────────────────────────────────────────────── | |
| 35 | say "[1/4] Checking prerequisites" | |
| 36 | command -v zip >/dev/null 2>&1 || fail "zip is not on PATH — install it (apt: zip / brew: zip) and retry" | |
| 37 | ok "zip found: $(command -v zip)" | |
| 38 | ||
| 39 | [[ -d "$SRC_DIR" ]] || fail "extension/gluecron.dxt/ missing — bad checkout?" | |
| 40 | [[ -f "$SRC_DIR/manifest.json" ]] || fail "manifest.json missing under $SRC_DIR" | |
| 41 | ok "source tree at $SRC_DIR" | |
| 42 | ||
| 43 | # ── 2. Validate manifest is parseable JSON ───────────────────────────────── | |
| 44 | say "[2/4] Validating manifest.json" | |
| 45 | if command -v bun >/dev/null 2>&1; then | |
| 46 | bun -e "JSON.parse(require('fs').readFileSync('$SRC_DIR/manifest.json','utf8'))" \ | |
| 47 | || fail "manifest.json is not valid JSON" | |
| 48 | elif command -v node >/dev/null 2>&1; then | |
| 49 | node -e "JSON.parse(require('fs').readFileSync('$SRC_DIR/manifest.json','utf8'))" \ | |
| 50 | || fail "manifest.json is not valid JSON" | |
| 51 | elif command -v python3 >/dev/null 2>&1; then | |
| 52 | python3 -c "import json,sys;json.load(open('$SRC_DIR/manifest.json'))" \ | |
| 53 | || fail "manifest.json is not valid JSON" | |
| 54 | else | |
| 55 | warn "no bun/node/python3 — skipping JSON validation" | |
| 56 | fi | |
| 57 | ok "manifest.json is valid" | |
| 58 | ||
| 59 | # ── 3. Regenerate placeholder assets if bun is available ─────────────────── | |
| 60 | say "[3/4] Refreshing placeholder assets" | |
| 61 | if command -v bun >/dev/null 2>&1 && [[ -f "$ROOT/scripts/build-dxt-assets.ts" ]]; then | |
| 62 | bun run "$ROOT/scripts/build-dxt-assets.ts" | |
| 63 | ok "assets refreshed" | |
| 64 | else | |
| 65 | warn "bun missing or build-dxt-assets.ts not found — using committed PNGs as-is" | |
| 66 | fi | |
| 67 | ||
| 68 | # ── 4. Zip → public/gluecron.dxt ──────────────────────────────────────────── | |
| 69 | say "[4/4] Packaging gluecron.dxt" | |
| 70 | mkdir -p "$OUT_DIR" | |
| 71 | # `zip -j` would flatten paths; we want manifest.json at the ZIP root so | |
| 72 | # Claude Desktop finds it. Use a clean temp dir + `cd` to keep the archive | |
| 73 | # rooted at the bundle directory itself. | |
| 74 | TMP_DIR="$(mktemp -d)" | |
| 75 | trap 'rm -rf "$TMP_DIR"' EXIT | |
| 76 | cp -R "$SRC_DIR/." "$TMP_DIR/" | |
| 77 | # Remove the previous archive so `zip` doesn't try to update an existing one. | |
| 78 | rm -f "$OUT_FILE" | |
| 79 | ( cd "$TMP_DIR" && zip -q -r "$OUT_FILE" . ) | |
| 80 | ok "wrote $OUT_FILE" | |
| 81 | ||
| 82 | SIZE=$(wc -c < "$OUT_FILE" | tr -d ' ') | |
| 83 | HUMAN=$(printf "%.1f KB" "$(echo "scale=1; $SIZE/1024" | bc 2>/dev/null || echo "$SIZE")" 2>/dev/null || echo "$SIZE bytes") | |
| 84 | ok "size: $HUMAN ($SIZE bytes)" | |
| 85 | ||
| 86 | printf "\nDone. Test locally:\n curl -I http://localhost:3000/gluecron.dxt\n\n" |