Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
claude/adoring-hopper-5x74bqclaude/affectionate-feynman-ykrf1hclaude/architecture-audit-design-wxprenclaude/build-status-update-3MXsfclaude/charming-meitner-mllb5rclaude/compare-gate-gluecron-s4mFQclaude/confident-faraday-tikcwbclaude/continue-work-XMTlIclaude/crontech-gluecron-deploy-7MIECclaude/crontech-platform-setup-SeKfwclaude/design-2026claude/ecstatic-ptolemy-jMdigclaude/enhance-github-integration-QNHdGclaude/fix-aa-loop-issue-PonMQclaude/fix-actions-and-processclaude/fix-desktop-errors-XqoW8claude/fix-red-workflowsclaude/fix-website-access-6FKJNclaude/gatetest-integration-hardeningclaude/github-audit-improvements-bDFr9claude/gluecron-launch-status-FoMRlclaude/hopeful-lamport-olfCTclaude/issue-to-pr-and-protectionsclaude/jolly-heisenberg-2sg1Qclaude/launch-preparation-QmTb6claude/new-session-xk1l7claude/plan-platform-architecture-kkN4yclaude/platform-analysis-roadmap-1nUGLclaude/platform-launch-assessment-8dWV8claude/polish-platform-release-AeDrUclaude/resume-previous-work-KzyLwclaude/review-crontech-handoff-qYEVqclaude/review-project-completeness-lHhS2claude/review-readme-docs-ulqPKclaude/serene-edison-rj87weclaude/setup-multi-repo-dev-BCwNQclaude/ship-fixes-and-tests-Jvz1cclaude/site-audit-competitive-pctlwgclaude/site-migration-vercel-XstpKclaude/standalone-product-repos-XHFTDcopilot/feat-smart-empty-states-keyboard-first-enhancementcopilot/feat-smart-morning-digest-review-context-restorecopilot/fix-and-process-workflowscopilot/update-ai-powered-code-reviewfeat/debt-mapfeat/push-policy-codeowners-hardeningfeat/smart-digest-contextfeat/stage-impactfeat/t1-secret-migrationfeat/u-polishfeat/w-self-hostfeat/w2-claude-configfix/agent-journey-orphan-sweepgatetest/auto-fix-1776586424172gatetest/auto-fix-1776586534814gatetest/auto-fix-1776590685143gatetest/auto-fix-1776590808199mainops/redeploy-retriggerstyle/dxt-cta-themeworktree-agent-a3377aad30d55da26worktree-agent-a7ef607b7ee1d6c74
install.sh12.7 KB · 308 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
#!/usr/bin/env bash
# =============================================================================
# Gluecron one-command install.
#
#   curl -sSL https://gluecron.com/install | bash
#
# What it does (every step is idempotent + verbose):
#   1. Verify git, curl, jq are on PATH
#   2. Resolve Gluecron host (default https://gluecron.com, env override)
#   3. Locate Claude Desktop config (macOS / Linux / WSL)
#   4. Sign in (env vars or interactive prompt) and capture session cookie
#   5. Mint a fresh PAT via POST /api/v2/auth/install-token
#   6. Merge a 'gluecron' MCP server entry into claude_desktop_config.json
#   7. If we're inside a GitHub-origin repo, offer to import it
#   8. Drop the Claude Code skill bundle into ~/.claude/skills/
#   9. Print a "you're done" success banner
#
# No third-party tools beyond plain curl, jq, git. Idempotent. Safe to re-run.
# =============================================================================

set -euo pipefail

# ── pretty printers (match scripts/bootstrap-hetzner.sh style) ───────────────
say()  { printf "\n\033[1;34m> %s\033[0m\n" "$*"; }
ok()   { printf "  \033[32mv\033[0m %s\n" "$*"; }
warn() { printf "  \033[33m!\033[0m %s\n" "$*"; }
fail() { printf "  \033[31mx\033[0m %s\n" "$*"; exit 1; }

# ── 1. Prerequisites ────────────────────────────────────────────────────────
say "[1/8] Checking prerequisites"
MISSING=()
for tool in git curl jq; do
  if ! command -v "$tool" >/dev/null 2>&1; then
    MISSING+=("$tool")
  fi
done
if [ "${#MISSING[@]}" -gt 0 ]; then
  warn "Missing tools: ${MISSING[*]}"
  echo "  Install them and re-run, e.g.:"
  for tool in "${MISSING[@]}"; do
    case "$tool" in
      jq)   echo "    macOS: brew install jq    |  Debian/Ubuntu: sudo apt-get install -y jq" ;;
      git)  echo "    macOS: xcode-select --install  |  Debian/Ubuntu: sudo apt-get install -y git" ;;
      curl) echo "    macOS: (preinstalled)     |  Debian/Ubuntu: sudo apt-get install -y curl" ;;
    esac
  done
  fail "Please install the missing tools above and re-run."
fi
ok "git, curl, jq present"

# ── 2. Host ─────────────────────────────────────────────────────────────────
say "[2/8] Resolving Gluecron host"
HOST="${GLUECRON_HOST:-https://gluecron.com}"
HOST="${HOST%/}" # strip trailing slash
ok "Using host: $HOST"

# ── 3. Locate Claude Desktop config ────────────────────────────────────────
say "[3/8] Locating Claude Desktop config"
UNAME_S="$(uname -s 2>/dev/null || echo unknown)"
MAC_CONF="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
LINUX_CONF="$HOME/.config/Claude/claude_desktop_config.json"
CLAUDE_CONF=""

case "$UNAME_S" in
  Darwin*)
    CLAUDE_CONF="$MAC_CONF"
    ;;
  Linux*)
    # WSL detection
    if grep -qi microsoft /proc/version 2>/dev/null; then
      if [ -d "$HOME/.config/Claude" ]; then
        CLAUDE_CONF="$LINUX_CONF"
      else
        CLAUDE_CONF="$LINUX_CONF"
        warn "WSL detected but no existing Claude config — using $CLAUDE_CONF"
      fi
    else
      CLAUDE_CONF="$LINUX_CONF"
    fi
    ;;
  *)
    warn "Unknown platform '$UNAME_S' — defaulting to macOS path."
    CLAUDE_CONF="$MAC_CONF"
    ;;
esac

mkdir -p "$(dirname "$CLAUDE_CONF")"
if [ ! -f "$CLAUDE_CONF" ]; then
  echo '{}' > "$CLAUDE_CONF"
  ok "Created empty $CLAUDE_CONF"
else
  ok "Found existing $CLAUDE_CONF"
fi

# ── 4. Sign in ──────────────────────────────────────────────────────────────
say "[4/8] Signing in to $HOST"
USERNAME="${GLUECRON_USERNAME:-}"
PASSWORD="${GLUECRON_PASSWORD:-}"
if [ -z "$USERNAME" ]; then
  if [ ! -t 0 ]; then
    fail "GLUECRON_USERNAME is unset and stdin is not a TTY. Re-run as: GLUECRON_USERNAME=you GLUECRON_PASSWORD=*** curl -sSL $HOST/install | bash"
  fi
  printf "  Gluecron username: "
  read -r USERNAME
fi
if [ -z "$PASSWORD" ]; then
  if [ ! -t 0 ]; then
    fail "GLUECRON_PASSWORD is unset and stdin is not a TTY."
  fi
  printf "  Gluecron password: "
  stty -echo
  read -r PASSWORD
  stty echo
  printf "\n"
fi

COOKIE_JAR="$(mktemp -t gluecron-cookies.XXXXXX)"
trap 'rm -f "$COOKIE_JAR"' EXIT

LOGIN_BODY="username=$(printf %s "$USERNAME" | jq -sRr @uri)&password=$(printf %s "$PASSWORD" | jq -sRr @uri)"
LOGIN_STATUS=$(
  curl -sS -o /dev/null -w "%{http_code}" \
    -X POST \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -c "$COOKIE_JAR" \
    --data "$LOGIN_BODY" \
    "$HOST/login" || echo 000
)
if ! grep -q "session" "$COOKIE_JAR" 2>/dev/null; then
  fail "Login failed (HTTP $LOGIN_STATUS). Check username/password."
fi
ok "Signed in as $USERNAME"

# ── 5. Mint PAT ─────────────────────────────────────────────────────────────
say "[5/8] Minting a fresh PAT"
SHORT_TS=$(date +%s | tail -c 7)
MINT_BODY=$(jq -nc --arg name "gluecron-install-$SHORT_TS" --arg scope "admin" \
  '{name: $name, scope: $scope}')
MINT_RESPONSE=$(
  curl -sS \
    -X POST \
    -H "Content-Type: application/json" \
    -b "$COOKIE_JAR" \
    --data "$MINT_BODY" \
    "$HOST/api/v2/auth/install-token"
)
PAT=$(printf %s "$MINT_RESPONSE" | jq -r '.token // empty')
if [ -z "$PAT" ]; then
  ERR=$(printf %s "$MINT_RESPONSE" | jq -r '.error // .hint // .')
  fail "PAT mint failed: $ERR"
fi
PAT_PREFIX=$(printf %s "$PAT" | cut -c1-12)
ok "Created PAT $PAT_PREFIX..."

# ── 6. Merge MCP server entry into Claude Desktop config ───────────────────
say "[6/8] Wiring Claude Desktop -> Gluecron MCP"
TMP_CONF="$(mktemp -t gluecron-conf.XXXXXX)"
jq --arg url "$HOST/mcp" --arg auth "Bearer $PAT" '
  . as $root
  | (.mcpServers // {}) as $servers
  | $root
  | .mcpServers = ($servers + {
      "gluecron": {
        "transport": "http",
        "url": $url,
        "headers": { "Authorization": $auth }
      }
    })
' "$CLAUDE_CONF" > "$TMP_CONF"
mv "$TMP_CONF" "$CLAUDE_CONF"
ok "Updated $CLAUDE_CONF"

# ── 7. Optional repo import ─────────────────────────────────────────────────
say "[7/8] Repo import (optional)"
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  ORIGIN_URL=$(git config --get remote.origin.url || true)
  if [ -n "$ORIGIN_URL" ] && printf %s "$ORIGIN_URL" | grep -q "github.com"; then
    if [ -t 0 ]; then
      printf "  Import this repo (%s) to Gluecron? [y/N] " "$ORIGIN_URL"
      read -r ANSWER
    else
      ANSWER="${GLUECRON_IMPORT:-n}"
    fi
    case "$ANSWER" in
      y|Y|yes|YES)
        IMPORT_BODY="repo_url=$(printf %s "$ORIGIN_URL" | jq -sRr @uri)"
        IMPORT_STATUS=$(
          curl -sS -o /dev/null -w "%{http_code}" \
            -X POST \
            -H "Authorization: Bearer $PAT" \
            -H "Content-Type: application/x-www-form-urlencoded" \
            --data "$IMPORT_BODY" \
            "$HOST/import/github/repo" || echo 000
        )
        case "$IMPORT_STATUS" in
          2*|3*) ok "Import dispatched (HTTP $IMPORT_STATUS)" ;;
          *)     warn "Import returned HTTP $IMPORT_STATUS — you can re-run from $HOST/import" ;;
        esac
        ;;
      *)
        ok "Skipped import"
        ;;
    esac
  else
    ok "No GitHub origin detected — skipping import"
  fi
else
  ok "Not inside a git repo — skipping import"
fi

# ── 8. Claude Code skill bundle ─────────────────────────────────────────────
# Drop the gluecron-pr / gluecron-issue / gluecron-review skills into
# ~/.claude/skills/ so they appear as slash commands inside Claude Code.
# Idempotent: each write overwrites the existing file.
say "[8/8] Installing Claude Code skill bundle (~/.claude/skills/)"
SKILLS_ROOT="$HOME/.claude/skills"
mkdir -p "$SKILLS_ROOT/gluecron-pr" "$SKILLS_ROOT/gluecron-issue" "$SKILLS_ROOT/gluecron-review"

cat > "$SKILLS_ROOT/gluecron-pr/SKILL.md" <<'GLUECRON_SKILL_PR_EOF'
---
name: gluecron-pr
description: Open, list, fetch, comment on, merge, or close pull requests on a Gluecron-hosted repository. Use this skill whenever the user references a Gluecron repo (origin URL contains "gluecron.com" or matches the GLUECRON_HOST env var) and asks to "open a PR", "merge", "review", "comment on PR #N", "list open PRs", or "close PR #N" on a repo that is NOT hosted on GitHub.
tools:
  - gluecron_create_pr
  - gluecron_get_pr
  - gluecron_list_prs
  - gluecron_comment_pr
  - gluecron_merge_pr
  - gluecron_close_pr
  - Bash
---

When invoked, drive the Gluecron MCP write surface to manage pull
requests on the active Gluecron-hosted repo. Detect owner/repo from
`git config --get remote.origin.url` (shapes:
`https://<HOST>/<owner>/<repo>.git`, `git@<HOST>:<owner>/<repo>.git` —
strip the `.git`). Default base branch:
`git symbolic-ref refs/remotes/origin/HEAD` (fall back to `main`).
Always read `git diff origin/<base>...HEAD` before opening a PR so the
title and body match the diff. See the bundled SKILL.md in this repo's
`.claude/skills/gluecron-pr/` for the full recipe and example prompts.
GLUECRON_SKILL_PR_EOF

cat > "$SKILLS_ROOT/gluecron-issue/SKILL.md" <<'GLUECRON_SKILL_ISSUE_EOF'
---
name: gluecron-issue
description: Create, list, comment on, close, or reopen issues on a Gluecron-hosted repository. Use this skill whenever the user is on a Gluecron repo (origin URL contains "gluecron.com" or matches the GLUECRON_HOST env var) and asks to "open an issue", "file a bug", "comment on #N", "close #N", or "reopen #N" on a repo that is NOT hosted on GitHub.
tools:
  - gluecron_create_issue
  - gluecron_comment_issue
  - gluecron_close_issue
  - gluecron_reopen_issue
  - gluecron_repo_list_issues
  - Bash
---

When invoked, drive the Gluecron MCP write surface to manage issues on
the active Gluecron-hosted repo. Detect owner/repo from
`git config --get remote.origin.url`. Common ops: file an issue with a
Markdown body (What happened / Expected / Repro), comment on an existing
issue, close, reopen, list open issues. Never bulk-close more than 5
issues in one tool sequence without re-confirming with the user.
GLUECRON_SKILL_ISSUE_EOF

cat > "$SKILLS_ROOT/gluecron-review/SKILL.md" <<'GLUECRON_SKILL_REVIEW_EOF'
---
name: gluecron-review
description: Act as a secondary AI code reviewer on a Gluecron-hosted pull request. Use this skill when the user asks Claude to "review PR #N", "give a second-opinion review", or "leave inline comments" on a Gluecron pull request. Complements Gluecron's built-in AI review.
tools:
  - gluecron_get_pr
  - gluecron_list_prs
  - gluecron_comment_pr
  - Bash
---

When invoked, act as a secondary reviewer on top of Gluecron's built-in
AI review pass (`src/lib/ai-review.ts`, marker
`<!-- gluecron-ai-review:summary -->`). Flow: fetch the PR via
`gluecron_get_pr`, fetch the diff locally via `git diff
origin/<base>...origin/<head>`, post one `gluecron_comment_pr` per
finding (file + line + suggestion), then a summary comment prefixed
with `<!-- claude-secondary-review:summary -->` and a verdict line
("**Verdict:** approved" or "**Verdict:** changes requested"). Do not
call `gluecron_merge_pr` from this skill.
GLUECRON_SKILL_REVIEW_EOF

ok "Wrote $SKILLS_ROOT/gluecron-pr/SKILL.md"
ok "Wrote $SKILLS_ROOT/gluecron-issue/SKILL.md"
ok "Wrote $SKILLS_ROOT/gluecron-review/SKILL.md"

# ── Done ────────────────────────────────────────────────────────────────────
printf "\n"
printf "\033[1;32m============================================================\033[0m\n"
printf "\033[1;32m  GLUECRON INSTALL COMPLETE\033[0m\n"
printf "\033[1;32m============================================================\033[0m\n"
printf "  Host:           %s\n" "$HOST"
printf "  PAT prefix:     %s...\n" "$PAT_PREFIX"
printf "  MCP config:     %s\n" "$CLAUDE_CONF"
printf "  Skills:         %s/{gluecron-pr,gluecron-issue,gluecron-review}\n" "$SKILLS_ROOT"
printf "\n"
printf "  v Done. Restart Claude Desktop and try:\n"
printf "      \"Open a PR on this repo with a one-line README fix\"\n"
printf "\n"
printf "  Tip: if you also use Claude Code in this repo, the\n"
printf "  .claude/settings.json at the repo root auto-configures\n"
printf "  the Gluecron MCP server. Set GLUECRON_PAT in your shell\n"
printf "  and future Code sessions wire up with no further config.\n"
printf "\n"