rewrite: refresh all blog posts for public audience
Merged overlapping posts: - forking-gitea + fork-dont-build → one post about the fork philosophy - fal-image-generation + image-generation-fal → one post about AI art pipeline Rewrote all posts with external/public voice: - Stronger hooks, concrete examples, punchier language - agentic-workflow: restructured around soul files + skills + numbers - agent-harness: clearer framing of 'what an agent harness is' - cloud-harness: tighter narrative about overnight agents - godot-optimisation: same depth, sharper opening - pre-commit-agent: clearer architecture, cost breakdown - studio-cli: reframed around identity/cold-start problem - blog-visual-upgrade: tightened the restyle story 10 posts total (9 markdown + 1 hand-authored HTML)
This commit is contained in:
+41
-80
@@ -2,31 +2,23 @@
|
||||
title: "A Pre-Commit Agent That Guards Your Secrets for $0.001"
|
||||
slug: pre-commit-agent
|
||||
date: "2026-05-25"
|
||||
description: "We built a pre-commit hook that calls DeepSeek V4 Flash to review every commit. It catches leaked secrets, classified terms, broken URLs, and drafts announcements --- for a tenth of a cent per commit."
|
||||
description: "We built a pre-commit hook that calls DeepSeek V4 Flash to review every commit. It catches leaked API keys, classified terms, broken URLs, and drafts announcements — for a tenth of a cent per commit."
|
||||
og_description: "A DeepSeek-powered pre-commit hook that catches leaks for $0.001/commit."
|
||||
og_image: "https://www.tinqs.com/img/og-cover.jpg"
|
||||
excerpt: "We built a pre-commit hook that calls DeepSeek V4 Flash to review every commit. It catches leaked secrets, classified terms, and broken URLs --- for a tenth of a cent."
|
||||
excerpt: "Too many things to remember before hitting commit. Don't leak API keys. Don't reference classified codenames. Don't link to deleted repos. We built a two-layer pre-commit hook — regex + LLM — that catches all of it for $0.001."
|
||||
author: "Ozan Bozkurt"
|
||||
author_initials: "OB"
|
||||
author_role: "CTO & Developer, Tinqs"
|
||||
---
|
||||
We have a problem that every small team has: too many things to remember before hitting commit. Don't leak API keys. Don't reference the classified AI codename in public blog posts. Don't link to GitHub repos we deleted six months ago. Don't push a blog post with a 90-character title. We built a pre-commit hook that uses a cheap LLM to check all of this automatically --- and it costs less than a tenth of a cent per commit.
|
||||
Every small team has the same problem: too many things to remember before `git commit`. Don't leak API keys. Don't reference the classified AI codename in public posts. Don't link to GitHub repos we deleted six months ago. Don't push a blog post with a 90-character title.
|
||||
|
||||
## The Problem
|
||||
A checklist in the README doesn't work. Humans skip checklists. Code review catches some issues but not all — reviewers focus on logic, not whether a URL points to a deleted org.
|
||||
|
||||
We maintain a docs repo that serves double duty. Internal files --- game design documents, architecture notes, agent configuration --- sit alongside a public blog and website. The internal side references classified codenames, machine hostnames, and internal URLs. The public side must never contain any of that.
|
||||
We built a pre-commit hook with two layers: a regex blocklist that's instant and free, and an LLM review that costs $0.001. Together they catch everything.
|
||||
|
||||
We also deleted all our GitHub repos in April 2026 and moved everything to our own Gitea platform. But old links keep creeping back in --- someone copies a URL from an old document, a blog post references the wrong remote. These are invisible bugs. The blog looks fine, the build passes, and three weeks later someone notices a dead link.
|
||||
## Layer 1: Regex blocklist (0ms, $0.00)
|
||||
|
||||
A checklist in the README doesn't work. Humans skip checklists. Code review catches some issues but not all --- reviewers focus on logic, not whether a URL points to a deleted GitHub org. We needed something automatic, fast, and cheap enough to run on every single commit.
|
||||
|
||||
## Two Layers: Regex + Agent
|
||||
|
||||
The hook has two layers. The first is instant and free. The second is smart and nearly free.
|
||||
|
||||
### Layer 1: Local Blocklist (0ms, $0.00)
|
||||
|
||||
A text file of regex patterns, each tagged with a scope and a message:
|
||||
A text file of patterns, each tagged with scope and message:
|
||||
|
||||
```
|
||||
public|\bCosmos\b|Classified codename — use "advanced colonist AI"
|
||||
@@ -36,60 +28,48 @@ all|AKIA[A-Z0-9]{16}|AWS access key leaked
|
||||
public|admin\.arikigame\.com|Internal admin URL in public content
|
||||
```
|
||||
|
||||
The scope field controls where the pattern is enforced. `all` means every file. `public` means only files under `website/` --- our public-facing content. This is critical. We *want* classified codenames in our internal architecture docs. We just don't want them in blog posts.
|
||||
The scope field controls where patterns apply. `all` means every file. `public` means only public-facing content — blog posts, website, marketing pages. We *want* classified codenames in internal architecture docs. We just don't want them in blog posts.
|
||||
|
||||
The blocklist runs grep against the staged diff. No network call, no API, no latency. If it finds a match, the commit is blocked immediately with a file path and explanation. This catches 80% of issues before the LLM ever wakes up.
|
||||
The blocklist runs grep against the staged diff. No network call, no API, no latency. Match found → commit blocked immediately with file path and explanation. This catches 80% of issues before the LLM wakes up.
|
||||
|
||||
### Layer 2: DeepSeek V4 Flash Review (~4s, $0.001)
|
||||
## Layer 2: DeepSeek V4 Flash review (~4s, $0.001)
|
||||
|
||||
If the commit touches public-facing files (`website/`, blog posts), the hook sends the staged diff to DeepSeek V4 Flash through our inference proxy. The system prompt tells the model exactly what to check:
|
||||
If the commit touches public-facing files, the hook sends the staged diff to DeepSeek V4 Flash. The system prompt tells it exactly what to check:
|
||||
|
||||
- **Leaked secrets** --- API keys, tokens, credentials that the regex might have missed
|
||||
- **Classified terms** --- codenames that aren't in the blocklist yet
|
||||
- **Internal URLs** --- references to internal services that shouldn't be public
|
||||
- **Blog quality** --- title length, meta description, slug consistency, missing fields
|
||||
- **Broken links** --- malformed URLs, obvious typos
|
||||
- **Announcements** --- if it's a new blog post, draft a one-line summary
|
||||
- **Leaked secrets** — API keys, tokens, credentials the regex might have missed
|
||||
- **Classified terms** — codenames not yet in the blocklist
|
||||
- **Internal URLs** — references to services that shouldn't be public
|
||||
- **Blog quality** — title length, meta description, slug consistency
|
||||
- **Broken links** — malformed URLs, obvious typos
|
||||
- **Announcements** — if it's a new blog post, draft a one-line summary
|
||||
|
||||
The model responds with structured JSON: errors (block the commit) or warnings (inform but allow). If the API is unreachable or times out, the commit proceeds --- the hook never blocks work for infrastructure reasons.
|
||||
The model responds with structured JSON: `errors` (block) or `warnings` (inform but allow). If the API is unreachable or times out, the commit proceeds — the hook never blocks work for infrastructure reasons.
|
||||
|
||||
## Why Not Pi?
|
||||
|
||||
Our [Pi fork](https://tinqs.com/tinqs/pi) is a full coding agent with tool calling, file I/O, and context management. It's what we use for overnight autonomous coding. But for pre-commit review, it's overkill.
|
||||
|
||||
A pre-commit hook needs to finish in under 5 seconds. Pi takes 2--3 seconds just to start the Node.js process and load extensions. The review itself is a single LLM call with a system prompt and a diff --- no tools needed, no file reads, no iteration. A direct curl to DeepSeek is faster and simpler.
|
||||
|
||||
That said, the hook is designed as a stepping stone. The blocklist patterns, the review prompt, and the classification logic are all reusable. When we build a Pi-based CI reviewer that runs on pull requests --- with tool access to read the full file, check links live, and verify image URLs --- it will use the same prompt and the same patterns. The pre-commit hook is the fast, cheap first pass. Pi is the thorough second pass.
|
||||
|
||||
## The Architecture
|
||||
## The architecture
|
||||
|
||||
```
|
||||
git commit
|
||||
↓
|
||||
.githooks/pre-commit (bash)
|
||||
↓
|
||||
Phase 0: Collect staged diff + classify files
|
||||
Phase 0: Collect staged diff + classify files (public vs internal)
|
||||
↓
|
||||
Phase 1: Regex blocklist scan (instant, free)
|
||||
→ Match found → BLOCK (exit 1)
|
||||
→ Match → BLOCK
|
||||
→ Clean → continue
|
||||
↓
|
||||
Phase 2: Public files changed?
|
||||
→ No → exit 0 (skip AI, no cost)
|
||||
→ No → exit 0 (skip AI review, zero cost)
|
||||
→ Yes → send diff to DeepSeek V4 Flash
|
||||
↓
|
||||
Phase 3: Parse JSON response
|
||||
→ Errors → BLOCK (exit 1)
|
||||
→ Errors → BLOCK
|
||||
→ Warnings → print, exit 0
|
||||
→ Announcement → print draft
|
||||
→ API failure → warn, exit 0
|
||||
→ API failure → warn, exit 0 (never block on infra)
|
||||
```
|
||||
|
||||
The hook lives in `.githooks/` inside the repo --- committed, version-controlled, shared by the whole team. A setup script configures `git config core.hooksPath` to point there. The LFS pre-push hook sits in the same directory.
|
||||
The hook lives in `.githooks/` — committed, version-controlled, shared by the team. A setup script points `git config core.hooksPath` there.
|
||||
|
||||
## What It Costs
|
||||
|
||||
The system prompt is ~500 tokens. An average diff is 2,000--4,000 tokens. The response is ~200 tokens. At DeepSeek V4 Flash rates:
|
||||
## What it costs
|
||||
|
||||
| | Tokens | Cost |
|
||||
|--|--------|------|
|
||||
@@ -97,53 +77,34 @@ The system prompt is ~500 tokens. An average diff is 2,000--4,000 tokens. The re
|
||||
| Output (JSON response) | ~200 | $0.00006 |
|
||||
| **Per commit** | | **$0.00062** |
|
||||
|
||||
Call it a tenth of a cent. Twenty commits a day across the team: **$0.012/day**. About **$0.40/month**.
|
||||
A tenth of a cent. Twenty commits a day: $0.012/day. About **$0.40/month**. Commits that only touch internal files skip the AI review entirely — zero cost.
|
||||
|
||||
Commits that only touch internal files (architecture docs, agent config, game design) skip the AI review entirely. Zero cost. The hook only calls DeepSeek when public-facing content changes.
|
||||
## What it caught (first week)
|
||||
|
||||
## What It Catches
|
||||
- **2 classified codename leaks** in draft blog posts — caught by blocklist
|
||||
- **1 GitHub URL** from an old copy-paste — caught by blocklist
|
||||
- **3 blog SEO warnings** — titles over 60 chars, missing og_description — caught by AI
|
||||
- **1 announcement draft** auto-generated when a new post was committed
|
||||
|
||||
In the first week:
|
||||
|
||||
- **2 classified codename leaks** in draft blog posts --- caught by the blocklist before the AI even ran
|
||||
- **1 GitHub URL** that crept back in from a copy-paste --- caught by the blocklist
|
||||
- **3 blog SEO warnings** --- titles over 60 characters, missing og_description --- caught by the AI review
|
||||
- **1 announcement draft** generated automatically when a new blog post was committed
|
||||
|
||||
Zero false positives on the blocklist (the patterns are specific enough). Two false positives from the AI (flagged an internal URL in a code example that was clearly illustrative, not a real link). We added a note to the prompt to ignore URLs inside fenced code blocks.
|
||||
Zero false positives on the blocklist. Two false positives from the AI — flagged an internal URL in a code example that was clearly illustrative. We added a note to the prompt: ignore URLs inside fenced code blocks.
|
||||
|
||||
## Setup
|
||||
|
||||
One command per machine:
|
||||
|
||||
```bash
|
||||
bash scripts/setup-hooks.sh
|
||||
bash scripts/setup-hooks.sh # or .\scripts\setup-hooks.ps1 on Windows
|
||||
export TINQS_HOOK_TOKEN=<your-token> # same PAT used for git push
|
||||
```
|
||||
|
||||
Or on Windows:
|
||||
That's it. Every `git commit` runs the two-layer review. Bypass with `git commit --no-verify` for emergencies.
|
||||
|
||||
```powershell
|
||||
.\scripts\setup-hooks.ps1
|
||||
```
|
||||
## The pattern: guard rails at the edge
|
||||
|
||||
Set your inference token:
|
||||
This is the same principle we apply everywhere: put the guard rail where the action happens. Don't rely on a human checklist. Don't wait for code review. Don't hope someone remembers.
|
||||
|
||||
```bash
|
||||
export TINQS_HOOK_TOKEN=<your-gitea-pat>
|
||||
```
|
||||
The pre-commit hook is $0.001 of prevention. A leaked API key in a public post is hours of rotation, revocation, and audit. A classified codename in a blog post is a confidentiality breach. A dead link is a broken experience nobody notices for weeks.
|
||||
|
||||
That's it. Every `git commit` now runs the two-layer review. Bypass with `git commit --no-verify` when you need to (emergencies, known false positives).
|
||||
|
||||
## The Pattern: Guard Rails at the Edge
|
||||
|
||||
This is the same pattern we apply everywhere: put the guard rail where the action happens. Don't rely on a human checklist. Don't wait for code review. Don't hope someone remembers.
|
||||
|
||||
The pre-commit hook is $0.001 worth of prevention. A leaked API key in a public blog post is hours of rotation, revocation, and audit. A classified codename in a public post is a confidentiality breach. A dead GitHub link is a broken user experience that nobody notices for weeks.
|
||||
|
||||
The tools exist. DeepSeek V4 Flash is cheap enough to call on every commit. The hook is 150 lines of bash. The blocklist is a text file. The total infrastructure cost is zero --- it runs on the developer's machine, calls an API we already pay for, and adds 4 seconds to the commit flow.
|
||||
|
||||
The age of agents doesn't just mean agents that write code. It means agents that watch the code you write.
|
||||
The tools exist. DeepSeek V4 Flash is cheap enough to call on every commit. The hook is 150 lines of bash. The blocklist is a text file. Total infrastructure cost: zero — it runs on the developer's machine, calls an API we already pay for, adds 4 seconds to the commit flow.
|
||||
|
||||
---
|
||||
|
||||
*The pre-commit hook is part of [Tinqs Studio](https://tinqs.com), our open platform for game development. The inference proxy, the blocklist patterns, and the review prompt are all open and reusable. We're building [Ariki](https://arikigame.com) with these tools --- every commit in the game repo runs through the same guard.*
|
||||
*The pre-commit hook is part of [Tinqs Studio](https://tinqs.com). The inference proxy, blocklist patterns, and review prompt are open and reusable. Every commit in [Ariki](https://arikigame.com) runs through the same guard.*
|
||||
|
||||
Reference in New Issue
Block a user