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
| # gluecron
AI-native code intelligence platform — git hosting, automated CI, and push-time gate enforcement.
## Source of truth: Gluecron (self-canonical, no GitHub mirror)
This repository self-hosts on Gluecron itself. The one canonical remote is
`https://gluecron.com/ccantynz/Gluecron.com.git`. **Gluecron is self-canonical:
there is no GitHub mirror or fallback.** Durability comes from the offsite
backup (`scripts/backup-offsite.sh` → rclone), not from GitHub. A fresh host
re-seeds from a restored backup (`scripts/restore.sh`), never from GitHub.
(Cutover status + operator steps: `docs/CUTOVER_RUNBOOK.md`.)
**For any AI session working in this repo:**
- Use the Gluecron MCP server. It is declared in `.mcp.json` at the
repo root (project scope — this is the file Claude Code actually
loads MCP servers from, on both web/cloud sessions and the CLI; the
old `mcpServers` block in `.claude/settings.json` was never read).
Tools: `gluecron_create_pr`, `gluecron_merge_pr`,
`gluecron_create_issue`, `gluecron_comment_pr`, etc. See
`src/lib/mcp-tools.ts` for the full 15-tool surface.
- Push the feature branch straight to the canonical remote —
`git push https://x:${GLUECRON_PAT}@gluecron.com/ccantynz/Gluecron.com.git HEAD:<branch>`
(requires `gluecron.com` in the environment's network allowlist) —
then open the PR with `gluecron_create_pr`. There is no GitHub fallback;
if gluecron.com is unreachable, stop and surface it rather than pushing
to GitHub.
- Do NOT call any `mcp__github__*` write tool. The settings file's
`permissions.deny` already blocks them; if you encounter a deny
error, switch to the equivalent `gluecron_*` tool.
- The `.claude/skills/gluecron-pr`, `gluecron-issue`, and
`gluecron-review` skills are the highest-leverage entry points for
routine work. Invoke them when the user mentions a PR, an issue,
or wants a second AI review pass.
- Auth: the `GLUECRON_PAT` env var holds the user's personal access
token. If it's missing, prompt the user to generate one at
`/settings/tokens` (admin scope required for the merge tools).
**Deploys are self-driven now.** Push to the canonical Gluecron remote
and `src/hooks/post-receive.ts` fires `scripts/self-deploy.sh` directly.
The live site reflects the push in ~25 seconds. Watch `/admin/deploys`
for the live step stream.
**Server:** `gluecron.com` → `66.42.121.161` (Vultr VPS, not Fly.io or Hetzner —
both are decommissioned). Working tree lives at `/opt/gluecron` on that box.
**Operator access (AI sessions included):** the box is on the owner's
Tailscale tailnet as `jarvis` (`100.109.131.122`) with **Tailscale SSH
enabled** — from an owner machine, `ssh root@100.109.131.122` just works
(no key setup). Public-internet SSH (port 22) is password-only and the git
SSH server port (2222) is not exposed; always go via Tailscale.
**Runtime layout on the box (verified 2026-07-12):**
- App runs via `docker compose -f docker-compose.standalone.yml` in
`/opt/gluecron` (services: `gluecron`, `postgres`, `autoheal`).
- **Database is Neon** (managed Postgres, `ep-solitary-fog-...aws.neon.tech`).
The app's `DATABASE_URL` (in `/opt/gluecron/.env`) points at Neon, so ALL
reads/writes and migrations go there — Neon provides PITR. NOTE: the compose
also starts a local `postgres` (pgvector/pg16) container, but the app IGNORES
it (it's leftover/unused dead weight, like the caddy service). Do NOT back up
or query the local container thinking it's production — target Neon via the
app's `DATABASE_URL`. (Verified 2026-07-13.)
- Bare repos live in the docker volume `gluecron_git-repos`
(host path `/var/lib/docker/volumes/gluecron_git-repos/_data`), mounted
into the container at `/data/repos`. The host-side `/data/repos` dir is
NOT the live store — always go through the volume path.
- Auto-deploy: `gluecron-update.timer` (60s) runs `scripts/auto-update.sh`
— fetches `origin main` in `/opt/gluecron` and rebuilds on change.
`origin` = the canonical Gluecron repo. If the timer is disabled, deploys
silently stop — check `systemctl list-timers 'gluecron-*'` first when the
live build looks stale (compare `/api/version` builtAt vs latest commit).
- Manual deploy: `cd /opt/gluecron && git fetch <src> main && git reset
--hard FETCH_HEAD && docker compose -f docker-compose.standalone.yml up
-d --build`, then `... exec -T gluecron bun run db:migrate`.
**To deploy:**
```bash
git push gluecron main
# or first-time setup:
git remote add gluecron https://x:${GLUECRON_PAT}@gluecron.com/ccantynz/Gluecron.com.git
```
**Do NOT use Vercel** — it has been disconnected.
**GitHub reality check (2026-07-12):** the old GitHub repo
(`ccantynz-alt/Gluecron.com`) is NOT frozen and is still writable — the
cutover runbook (docs/CUTOVER_RUNBOOK.md) was designed but its operator
phases were never fully executed. GitHub remains the emergency deploy
source (`git fetch https://github.com/ccantynz-alt/Gluecron.com.git main`
on the box) until offsite backups are armed and a restore drill has
passed. Do not delete or archive the GitHub repo before that. Prefer the
canonical Gluecron remote for normal work; keep GitHub in sync until the
runbook's Phase 4 criteria are actually met.
## READ FIRST — every session
**`BUILD_BIBLE.md` is mandatory reading for every Claude agent before any code changes.**
It contains:
- Agent policy (do-not-undo rule, continuous-build rule)
- GitHub parity scorecard (what's shipped vs missing)
- Numbered build plan (Blocks A–H)
- Locked components that cannot be altered without owner permission
- Session workflow
Do not skip it. Do not refactor locked files. Do not stop mid-block.
## Stack
- **Runtime:** Bun
- **Framework:** Hono (with JSX for server-rendered views)
- **Database:** Drizzle ORM + Neon (managed Postgres) in prod
- **Git:** Smart HTTP protocol via git CLI subprocesses
## Development
```bash
bun install # install dependencies
bun dev # start dev server (hot reload)
bun test # run tests
bun run db:migrate # run database migrations
```
## Architecture
> Note (2026-06-10): the tree below is illustrative, not exhaustive — the
> platform has grown to ~190 route files in `src/routes/` and 161 tables in
> `src/db/schema.ts`. `BUILD_BIBLE.md` §2 is the authoritative feature map.
```
src/
index.ts Entry point (Bun server)
app.tsx Hono app composition + error handlers
lib/
config.ts Environment config (getters, reads env at access time)
auth.ts Password hashing (bcrypt), session tokens
highlight.ts Syntax highlighting (highlight.js, 40+ languages)
markdown.ts Markdown rendering (GFM + syntax highlighting)
db/
schema.ts Drizzle schema (all tables)
index.ts Lazy DB connection (proxy pattern)
migrate.ts Migration runner
git/
repository.ts Git operations (tree, blob, commits, diff, branches, blame, search, raw)
protocol.ts Smart HTTP protocol (pkt-line, service RPC)
hooks/
post-receive.ts GateTest + optional deploy webhook on push
middleware/
auth.ts softAuth + requireAuth middleware
routes/
git.ts Git HTTP endpoints (clone/push)
api.ts REST API (repo CRUD, setup)
auth.tsx Register, login, logout (web + API)
web.tsx Web UI (file browser, commits, diffs, search, blame, raw)
issues.tsx Issue tracker (CRUD, comments, close/reopen)
pulls.tsx Pull requests (create, review, merge, close)
editor.tsx Web file editor (create/edit via git plumbing)
compare.tsx Branch comparison (diff + commit list)
settings.tsx User settings (profile, SSH keys)
repo-settings.tsx Repository settings (description, visibility, delete)
webhooks.tsx Webhook management + delivery engine
fork.ts Repository forking
explore.tsx Explore/discover public repos
tokens.tsx Personal access tokens
contributors.tsx Contributor list + commit activity graph
views/
layout.tsx HTML shell + CSS (dark theme) + auth-aware nav
components.tsx UI components (file table, commit list, diff viewer, etc.)
```
## Database Schema
- `users` — accounts with bcrypt password hashing
- `sessions` — cookie-based auth sessions (30 day expiry)
- `repositories` — repos with fork tracking, star/fork/issue counts
- `stars` — user-repo star relationships
- `issues` — issue tracker with open/closed state
- `issue_comments` — threaded comments on issues
- `labels` + `issue_labels` — issue categorization
- `pull_requests` — PRs with base/head branches, open/closed/merged state
- `pr_comments` — PR comments with AI review flag + file/line annotations
- `activity_feed` — event log for repos
- `webhooks` — registered webhook URLs with HMAC secret + event filtering
- `api_tokens` — personal access tokens with SHA-256 hashing
- `repo_topics` — repository tags for discoverability
- `ssh_keys` — user SSH public keys
## Integrations
- **GateTest (optional):** third-party security scanner. When `GATETEST_URL` is set, `git push` POSTs to it; inbound results accepted at `POST /api/hooks/gatetest`.
- **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).
- **Webhooks:** POST to user-registered URLs on push/issue/PR/star events with HMAC signatures.
## Environment Variables
See `.env.example` for required variables. Key ones:
- `DATABASE_URL` — PostgreSQL connection string (prod: Neon; set in `/opt/gluecron/.env`)
- `GIT_REPOS_PATH` — directory for bare git repos (default: `./repos`)
- `PORT` — HTTP port (default: 3000)
## Deployment
- **Production server:** `66.42.121.161` (`gluecron.com`) — VPS running Bun directly via systemd.
- **Deploy trigger:** `git push gluecron main` → `post-receive.ts` → `scripts/self-deploy.sh` → systemd reload.
- **Fly.io:** decommissioned (fly.toml kept for reference, not active).
- **Vercel:** disconnected — do not reconnect.
- **Database:** Neon (managed Postgres) via `DATABASE_URL`; has built-in PITR.
- **Logs:** `/var/log/gluecron-self-deploy.log` on the server; live stream at `/admin/deploys`.
## Skills available for this project
Claude Code skill bundle for the Gluecron MCP write surface lives in
`.claude/skills/`. The install script (`scripts/install.sh`) copies these
into `~/.claude/skills/` so they are available across all projects:
- **`gluecron-pr`** — open, list, fetch, comment on, merge, or close pull
requests on a Gluecron-hosted repository.
- **`gluecron-issue`** — create, list, comment on, close, or reopen issues
on a Gluecron-hosted repository.
- **`gluecron-review`** — act as a secondary AI code reviewer on a
Gluecron PR; complements the built-in `src/lib/ai-review.ts` pass.
All three skills drive the K1 MCP write tools defined in
`src/lib/mcp-tools.ts` (`gluecron_create_issue`, `gluecron_create_pr`,
`gluecron_merge_pr`, etc.). They auto-invoke when the active repo's
origin URL contains `gluecron.com` or matches `$GLUECRON_HOST`.
|