CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
CLAUDE.md
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| fc1817a | 1 | # gluecron |
| 2 | ||
| 90fa787 | 3 | AI-native code intelligence platform — git hosting, automated CI, and push-time gate enforcement. |
| fc1817a | 4 | |
| 5472bea | 5 | ## Source of truth: Gluecron (self-canonical, no GitHub mirror) |
| 3b99c5f | 6 | |
| 5472bea | 7 | This repository self-hosts on Gluecron itself. The one canonical remote is |
| 8 | `https://gluecron.com/ccantynz/Gluecron.com.git`. **Gluecron is self-canonical: | |
| 9 | there is no GitHub mirror or fallback.** Durability comes from the offsite | |
| 10 | backup (`scripts/backup-offsite.sh` → rclone), not from GitHub. A fresh host | |
| 11 | re-seeds from a restored backup (`scripts/restore.sh`), never from GitHub. | |
| 12 | (Cutover status + operator steps: `docs/CUTOVER_RUNBOOK.md`.) | |
| 3b99c5f | 13 | |
| 14 | **For any AI session working in this repo:** | |
| 15 | ||
| 4cd9a67 | 16 | - Use the Gluecron MCP server. It is declared in `.mcp.json` at the |
| 17 | repo root (project scope — this is the file Claude Code actually | |
| 18 | loads MCP servers from, on both web/cloud sessions and the CLI; the | |
| 19 | old `mcpServers` block in `.claude/settings.json` was never read). | |
| 20 | Tools: `gluecron_create_pr`, `gluecron_merge_pr`, | |
| 3b99c5f | 21 | `gluecron_create_issue`, `gluecron_comment_pr`, etc. See |
| 22 | `src/lib/mcp-tools.ts` for the full 15-tool surface. | |
| 5472bea | 23 | - Push the feature branch straight to the canonical remote — |
| 4cd9a67 | 24 | `git push https://x:${GLUECRON_PAT}@gluecron.com/ccantynz/Gluecron.com.git HEAD:<branch>` |
| 25 | (requires `gluecron.com` in the environment's network allowlist) — | |
| 5472bea | 26 | then open the PR with `gluecron_create_pr`. There is no GitHub fallback; |
| 27 | if gluecron.com is unreachable, stop and surface it rather than pushing | |
| 28 | to GitHub. | |
| 3b99c5f | 29 | - Do NOT call any `mcp__github__*` write tool. The settings file's |
| 30 | `permissions.deny` already blocks them; if you encounter a deny | |
| 31 | error, switch to the equivalent `gluecron_*` tool. | |
| 32 | - The `.claude/skills/gluecron-pr`, `gluecron-issue`, and | |
| 33 | `gluecron-review` skills are the highest-leverage entry points for | |
| 34 | routine work. Invoke them when the user mentions a PR, an issue, | |
| 35 | or wants a second AI review pass. | |
| 36 | - Auth: the `GLUECRON_PAT` env var holds the user's personal access | |
| 37 | token. If it's missing, prompt the user to generate one at | |
| 38 | `/settings/tokens` (admin scope required for the merge tools). | |
| 39 | ||
| ab45e6a | 40 | **Deploys are self-driven now.** Push to the canonical Gluecron remote |
| 41 | and `src/hooks/post-receive.ts` fires `scripts/self-deploy.sh` directly. | |
| 42 | The live site reflects the push in ~25 seconds. Watch `/admin/deploys` | |
| 43 | for the live step stream. | |
| 44 | ||
| 8fcfd61 | 45 | **Server:** `gluecron.com` → `66.42.121.161` (Vultr VPS, not Fly.io or Hetzner — |
| ab45e6a | 46 | both are decommissioned). Working tree lives at `/opt/gluecron` on that box. |
| 47 | ||
| 8fcfd61 | 48 | **Operator access (AI sessions included):** the box is on the owner's |
| 49 | Tailscale tailnet as `jarvis` (`100.109.131.122`) with **Tailscale SSH | |
| 50 | enabled** — from an owner machine, `ssh root@100.109.131.122` just works | |
| 51 | (no key setup). Public-internet SSH (port 22) is password-only and the git | |
| 52 | SSH server port (2222) is not exposed; always go via Tailscale. | |
| 53 | ||
| 54 | **Runtime layout on the box (verified 2026-07-12):** | |
| 55 | - App runs via `docker compose -f docker-compose.standalone.yml` in | |
| 56 | `/opt/gluecron` (services: `gluecron`, `postgres`, `autoheal`). | |
| d24a155 | 57 | - **Database is Neon** (managed Postgres, `ep-solitary-fog-...aws.neon.tech`). |
| 58 | The app's `DATABASE_URL` (in `/opt/gluecron/.env`) points at Neon, so ALL | |
| 59 | reads/writes and migrations go there — Neon provides PITR. NOTE: the compose | |
| 60 | also starts a local `postgres` (pgvector/pg16) container, but the app IGNORES | |
| 61 | it (it's leftover/unused dead weight, like the caddy service). Do NOT back up | |
| 62 | or query the local container thinking it's production — target Neon via the | |
| 63 | app's `DATABASE_URL`. (Verified 2026-07-13.) | |
| 8fcfd61 | 64 | - Bare repos live in the docker volume `gluecron_git-repos` |
| 65 | (host path `/var/lib/docker/volumes/gluecron_git-repos/_data`), mounted | |
| 66 | into the container at `/data/repos`. The host-side `/data/repos` dir is | |
| 67 | NOT the live store — always go through the volume path. | |
| 68 | - Auto-deploy: `gluecron-update.timer` (60s) runs `scripts/auto-update.sh` | |
| 69 | — fetches `origin main` in `/opt/gluecron` and rebuilds on change. | |
| 70 | `origin` = the canonical Gluecron repo. If the timer is disabled, deploys | |
| 71 | silently stop — check `systemctl list-timers 'gluecron-*'` first when the | |
| 72 | live build looks stale (compare `/api/version` builtAt vs latest commit). | |
| 73 | - Manual deploy: `cd /opt/gluecron && git fetch <src> main && git reset | |
| 74 | --hard FETCH_HEAD && docker compose -f docker-compose.standalone.yml up | |
| 75 | -d --build`, then `... exec -T gluecron bun run db:migrate`. | |
| 76 | ||
| ab45e6a | 77 | **To deploy:** |
| 78 | ```bash | |
| 79 | git push gluecron main | |
| 80 | # or first-time setup: | |
| 81 | git remote add gluecron https://x:${GLUECRON_PAT}@gluecron.com/ccantynz/Gluecron.com.git | |
| 82 | ``` | |
| 83 | ||
| 8fcfd61 | 84 | **Do NOT use Vercel** — it has been disconnected. |
| 85 | ||
| 86 | **GitHub reality check (2026-07-12):** the old GitHub repo | |
| 87 | (`ccantynz-alt/Gluecron.com`) is NOT frozen and is still writable — the | |
| 88 | cutover runbook (docs/CUTOVER_RUNBOOK.md) was designed but its operator | |
| 89 | phases were never fully executed. GitHub remains the emergency deploy | |
| 90 | source (`git fetch https://github.com/ccantynz-alt/Gluecron.com.git main` | |
| 91 | on the box) until offsite backups are armed and a restore drill has | |
| 92 | passed. Do not delete or archive the GitHub repo before that. Prefer the | |
| 93 | canonical Gluecron remote for normal work; keep GitHub in sync until the | |
| 94 | runbook's Phase 4 criteria are actually met. | |
| 3b99c5f | 95 | |
| 9ab6971 | 96 | ## READ FIRST — every session |
| 97 | ||
| 98 | **`BUILD_BIBLE.md` is mandatory reading for every Claude agent before any code changes.** | |
| 99 | ||
| 100 | It contains: | |
| 101 | - Agent policy (do-not-undo rule, continuous-build rule) | |
| 102 | - GitHub parity scorecard (what's shipped vs missing) | |
| 103 | - Numbered build plan (Blocks A–H) | |
| 104 | - Locked components that cannot be altered without owner permission | |
| 105 | - Session workflow | |
| 106 | ||
| 107 | Do not skip it. Do not refactor locked files. Do not stop mid-block. | |
| 108 | ||
| fc1817a | 109 | ## Stack |
| 110 | ||
| 111 | - **Runtime:** Bun | |
| 112 | - **Framework:** Hono (with JSX for server-rendered views) | |
| d24a155 | 113 | - **Database:** Drizzle ORM + Neon (managed Postgres) in prod |
| fc1817a | 114 | - **Git:** Smart HTTP protocol via git CLI subprocesses |
| 115 | ||
| 116 | ## Development | |
| 117 | ||
| 118 | ```bash | |
| 119 | bun install # install dependencies | |
| 120 | bun dev # start dev server (hot reload) | |
| 121 | bun test # run tests | |
| 122 | bun run db:migrate # run database migrations | |
| 123 | ``` | |
| 124 | ||
| 125 | ## Architecture | |
| 126 | ||
| 74a8784 | 127 | > Note (2026-06-10): the tree below is illustrative, not exhaustive — the |
| 128 | > platform has grown to ~190 route files in `src/routes/` and 161 tables in | |
| 129 | > `src/db/schema.ts`. `BUILD_BIBLE.md` §2 is the authoritative feature map. | |
| 130 | ||
| fc1817a | 131 | ``` |
| 132 | src/ | |
| 43de941 | 133 | index.ts Entry point (Bun server) |
| 134 | app.tsx Hono app composition + error handlers | |
| 135 | lib/ | |
| 136 | config.ts Environment config (getters, reads env at access time) | |
| 137 | auth.ts Password hashing (bcrypt), session tokens | |
| 138 | highlight.ts Syntax highlighting (highlight.js, 40+ languages) | |
| 139 | markdown.ts Markdown rendering (GFM + syntax highlighting) | |
| fc1817a | 140 | db/ |
| 43de941 | 141 | schema.ts Drizzle schema (all tables) |
| 142 | index.ts Lazy DB connection (proxy pattern) | |
| 143 | migrate.ts Migration runner | |
| fc1817a | 144 | git/ |
| 43de941 | 145 | repository.ts Git operations (tree, blob, commits, diff, branches, blame, search, raw) |
| 146 | protocol.ts Smart HTTP protocol (pkt-line, service RPC) | |
| fc1817a | 147 | hooks/ |
| 90fa787 | 148 | post-receive.ts GateTest + optional deploy webhook on push |
| 43de941 | 149 | middleware/ |
| 150 | auth.ts softAuth + requireAuth middleware | |
| fc1817a | 151 | routes/ |
| 43de941 | 152 | git.ts Git HTTP endpoints (clone/push) |
| 153 | api.ts REST API (repo CRUD, setup) | |
| 154 | auth.tsx Register, login, logout (web + API) | |
| 155 | web.tsx Web UI (file browser, commits, diffs, search, blame, raw) | |
| 156 | issues.tsx Issue tracker (CRUD, comments, close/reopen) | |
| 157 | pulls.tsx Pull requests (create, review, merge, close) | |
| 158 | editor.tsx Web file editor (create/edit via git plumbing) | |
| 159 | compare.tsx Branch comparison (diff + commit list) | |
| 160 | settings.tsx User settings (profile, SSH keys) | |
| 161 | repo-settings.tsx Repository settings (description, visibility, delete) | |
| 162 | webhooks.tsx Webhook management + delivery engine | |
| 163 | fork.ts Repository forking | |
| 164 | explore.tsx Explore/discover public repos | |
| 165 | tokens.tsx Personal access tokens | |
| 166 | contributors.tsx Contributor list + commit activity graph | |
| fc1817a | 167 | views/ |
| 43de941 | 168 | layout.tsx HTML shell + CSS (dark theme) + auth-aware nav |
| 169 | components.tsx UI components (file table, commit list, diff viewer, etc.) | |
| fc1817a | 170 | ``` |
| 171 | ||
| 43de941 | 172 | ## Database Schema |
| 173 | ||
| 174 | - `users` — accounts with bcrypt password hashing | |
| 175 | - `sessions` — cookie-based auth sessions (30 day expiry) | |
| 176 | - `repositories` — repos with fork tracking, star/fork/issue counts | |
| 177 | - `stars` — user-repo star relationships | |
| 178 | - `issues` — issue tracker with open/closed state | |
| 179 | - `issue_comments` — threaded comments on issues | |
| 180 | - `labels` + `issue_labels` — issue categorization | |
| 181 | - `pull_requests` — PRs with base/head branches, open/closed/merged state | |
| 182 | - `pr_comments` — PR comments with AI review flag + file/line annotations | |
| 183 | - `activity_feed` — event log for repos | |
| 184 | - `webhooks` — registered webhook URLs with HMAC secret + event filtering | |
| 185 | - `api_tokens` — personal access tokens with SHA-256 hashing | |
| 186 | - `repo_topics` — repository tags for discoverability | |
| 187 | - `ssh_keys` — user SSH public keys | |
| 188 | ||
| fc1817a | 189 | ## Integrations |
| 190 | ||
| 90fa787 | 191 | - **GateTest (optional):** third-party security scanner. When `GATETEST_URL` is set, `git push` POSTs to it; inbound results accepted at `POST /api/hooks/gatetest`. |
| 9ecf5a4 | 192 | - **Outbound deploy webhook (optional):** when `VAPRON_DEPLOY_URL` is set (legacy `CRONTECH_DEPLOY_URL` honored), pushes to the default branch POST to Vapron (formerly Crontech). |
| 90fa787 | 193 | - **Webhooks:** POST to user-registered URLs on push/issue/PR/star events with HMAC signatures. |
| fc1817a | 194 | |
| 195 | ## Environment Variables | |
| 196 | ||
| 197 | See `.env.example` for required variables. Key ones: | |
| d24a155 | 198 | - `DATABASE_URL` — PostgreSQL connection string (prod: Neon; set in `/opt/gluecron/.env`) |
| fc1817a | 199 | - `GIT_REPOS_PATH` — directory for bare git repos (default: `./repos`) |
| 200 | - `PORT` — HTTP port (default: 3000) | |
| fc0785e | 201 | |
| 202 | ## Deployment | |
| 203 | ||
| ab45e6a | 204 | - **Production server:** `66.42.121.161` (`gluecron.com`) — VPS running Bun directly via systemd. |
| 205 | - **Deploy trigger:** `git push gluecron main` → `post-receive.ts` → `scripts/self-deploy.sh` → systemd reload. | |
| 206 | - **Fly.io:** decommissioned (fly.toml kept for reference, not active). | |
| 207 | - **Vercel:** disconnected — do not reconnect. | |
| d24a155 | 208 | - **Database:** Neon (managed Postgres) via `DATABASE_URL`; has built-in PITR. |
| ab45e6a | 209 | - **Logs:** `/var/log/gluecron-self-deploy.log` on the server; live stream at `/admin/deploys`. |
| 43095dc | 210 | |
| 211 | ## Skills available for this project | |
| 212 | ||
| 213 | Claude Code skill bundle for the Gluecron MCP write surface lives in | |
| 214 | `.claude/skills/`. The install script (`scripts/install.sh`) copies these | |
| 215 | into `~/.claude/skills/` so they are available across all projects: | |
| 216 | ||
| 217 | - **`gluecron-pr`** — open, list, fetch, comment on, merge, or close pull | |
| 218 | requests on a Gluecron-hosted repository. | |
| 219 | - **`gluecron-issue`** — create, list, comment on, close, or reopen issues | |
| 220 | on a Gluecron-hosted repository. | |
| 221 | - **`gluecron-review`** — act as a secondary AI code reviewer on a | |
| 222 | Gluecron PR; complements the built-in `src/lib/ai-review.ts` pass. | |
| 223 | ||
| 224 | All three skills drive the K1 MCP write tools defined in | |
| 225 | `src/lib/mcp-tools.ts` (`gluecron_create_issue`, `gluecron_create_pr`, | |
| 226 | `gluecron_merge_pr`, etc.). They auto-invoke when the active repo's | |
| 227 | origin URL contains `gluecron.com` or matches `$GLUECRON_HOST`. |